aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/include/clang/AST/Redeclarable.h
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang16/include/clang/AST/Redeclarable.h
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang16/include/clang/AST/Redeclarable.h')
-rw-r--r--contrib/libs/clang16/include/clang/AST/Redeclarable.h440
1 files changed, 440 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/AST/Redeclarable.h b/contrib/libs/clang16/include/clang/AST/Redeclarable.h
new file mode 100644
index 0000000000..056deeedc1
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/AST/Redeclarable.h
@@ -0,0 +1,440 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Redeclarable.h - Base for Decls that can be redeclared --*- C++ -*-====//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Redeclarable interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_REDECLARABLE_H
+#define LLVM_CLANG_AST_REDECLARABLE_H
+
+#include "clang/AST/ExternalASTSource.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+
+// Some notes on redeclarables:
+//
+// - Every redeclarable is on a circular linked list.
+//
+// - Every decl has a pointer to the first element of the chain _and_ a
+// DeclLink that may point to one of 3 possible states:
+// - the "previous" (temporal) element in the chain
+// - the "latest" (temporal) element in the chain
+// - the "uninitialized-latest" value (when newly-constructed)
+//
+// - The first element is also often called the canonical element. Every
+// element has a pointer to it so that "getCanonical" can be fast.
+//
+// - Most links in the chain point to previous, except the link out of
+// the first; it points to latest.
+//
+// - Elements are called "first", "previous", "latest" or
+// "most-recent" when referring to temporal order: order of addition
+// to the chain.
+//
+// - It's easiest to just ignore the implementation of DeclLink when making
+// sense of the redeclaration chain.
+//
+// - There's also a "definition" link for several types of
+// redeclarable, where only one definition should exist at any given
+// time (and the defn pointer is stored in the decl's "data" which
+// is copied to every element on the chain when it's changed).
+//
+// Here is some ASCII art:
+//
+// "first" "latest"
+// "canonical" "most recent"
+// +------------+ first +--------------+
+// | | <--------------------------- | |
+// | | | |
+// | | | |
+// | | +--------------+ | |
+// | | first | | | |
+// | | <---- | | | |
+// | | | | | |
+// | @class A | link | @interface A | link | @class A |
+// | seen first | <---- | seen second | <---- | seen third |
+// | | | | | |
+// +------------+ +--------------+ +--------------+
+// | data | defn | data | defn | data |
+// | | ----> | | <---- | |
+// +------------+ +--------------+ +--------------+
+// | | ^ ^
+// | |defn | |
+// | link +-----+ |
+// +-->-------------------------------------------+
+
+/// Provides common interface for the Decls that can be redeclared.
+template<typename decl_type>
+class Redeclarable {
+protected:
+ class DeclLink {
+ /// A pointer to a known latest declaration, either statically known or
+ /// generationally updated as decls are added by an external source.
+ using KnownLatest =
+ LazyGenerationalUpdatePtr<const Decl *, Decl *,
+ &ExternalASTSource::CompleteRedeclChain>;
+
+ /// We store a pointer to the ASTContext in the UninitializedLatest
+ /// pointer, but to avoid circular type dependencies when we steal the low
+ /// bits of this pointer, we use a raw void* here.
+ using UninitializedLatest = const void *;
+
+ using Previous = Decl *;
+
+ /// A pointer to either an uninitialized latest declaration (where either
+ /// we've not yet set the previous decl or there isn't one), or to a known
+ /// previous declaration.
+ using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>;
+
+ mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Link;
+
+ public:
+ enum PreviousTag { PreviousLink };
+ enum LatestTag { LatestLink };
+
+ DeclLink(LatestTag, const ASTContext &Ctx)
+ : Link(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
+ DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {}
+
+ bool isFirst() const {
+ return Link.is<KnownLatest>() ||
+ // FIXME: 'template' is required on the next line due to an
+ // apparent clang bug.
+ Link.get<NotKnownLatest>().template is<UninitializedLatest>();
+ }
+
+ decl_type *getPrevious(const decl_type *D) const {
+ if (Link.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Link.get<NotKnownLatest>();
+ if (NKL.is<Previous>())
+ return static_cast<decl_type*>(NKL.get<Previous>());
+
+ // Allocate the generational 'most recent' cache now, if needed.
+ Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ const_cast<decl_type *>(D));
+ }
+
+ return static_cast<decl_type*>(Link.get<KnownLatest>().get(D));
+ }
+
+ void setPrevious(decl_type *D) {
+ assert(!isFirst() && "decl became non-canonical unexpectedly");
+ Link = Previous(D);
+ }
+
+ void setLatest(decl_type *D) {
+ assert(isFirst() && "decl became canonical unexpectedly");
+ if (Link.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Link.get<NotKnownLatest>();
+ Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ D);
+ } else {
+ auto Latest = Link.get<KnownLatest>();
+ Latest.set(D);
+ Link = Latest;
+ }
+ }
+
+ void markIncomplete() { Link.get<KnownLatest>().markIncomplete(); }
+
+ Decl *getLatestNotUpdated() const {
+ assert(isFirst() && "expected a canonical decl");
+ if (Link.is<NotKnownLatest>())
+ return nullptr;
+ return Link.get<KnownLatest>().getNotUpdated();
+ }
+ };
+
+ static DeclLink PreviousDeclLink(decl_type *D) {
+ return DeclLink(DeclLink::PreviousLink, D);
+ }
+
+ static DeclLink LatestDeclLink(const ASTContext &Ctx) {
+ return DeclLink(DeclLink::LatestLink, Ctx);
+ }
+
+ /// Points to the next redeclaration in the chain.
+ ///
+ /// If isFirst() is false, this is a link to the previous declaration
+ /// of this same Decl. If isFirst() is true, this is the first
+ /// declaration and Link points to the latest declaration. For example:
+ ///
+ /// #1 int f(int x, int y = 1); // <pointer to #3, true>
+ /// #2 int f(int x = 0, int y); // <pointer to #1, false>
+ /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
+ ///
+ /// If there is only one declaration, it is <pointer to self, true>
+ DeclLink RedeclLink;
+
+ decl_type *First;
+
+ decl_type *getNextRedeclaration() const {
+ return RedeclLink.getPrevious(static_cast<const decl_type *>(this));
+ }
+
+public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class IncrementalParser;
+
+ Redeclarable(const ASTContext &Ctx)
+ : RedeclLink(LatestDeclLink(Ctx)),
+ First(static_cast<decl_type *>(this)) {}
+
+ /// Return the previous declaration of this declaration or NULL if this
+ /// is the first declaration.
+ decl_type *getPreviousDecl() {
+ if (!RedeclLink.isFirst())
+ return getNextRedeclaration();
+ return nullptr;
+ }
+ const decl_type *getPreviousDecl() const {
+ return const_cast<decl_type *>(
+ static_cast<const decl_type*>(this))->getPreviousDecl();
+ }
+
+ /// Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDecl() { return First; }
+
+ /// Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDecl() const { return First; }
+
+ /// True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const { return RedeclLink.isFirst(); }
+
+ /// Returns the most recent (re)declaration of this declaration.
+ decl_type *getMostRecentDecl() {
+ return getFirstDecl()->getNextRedeclaration();
+ }
+
+ /// Returns the most recent (re)declaration of this declaration.
+ const decl_type *getMostRecentDecl() const {
+ return getFirstDecl()->getNextRedeclaration();
+ }
+
+ /// Set the previous declaration. If PrevDecl is NULL, set this as the
+ /// first and only declaration.
+ void setPreviousDecl(decl_type *PrevDecl);
+
+ /// Iterates through all the redeclarations of the same decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ decl_type *Current = nullptr;
+ decl_type *Starter;
+ bool PassedFirst = false;
+
+ public:
+ using value_type = decl_type *;
+ using reference = decl_type *;
+ using pointer = decl_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ redecl_iterator() = default;
+ explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) {}
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Make sure we don't infinitely loop on an invalid redecl chain. This
+ // should never happen.
+ if (Current->isFirstDecl()) {
+ if (PassedFirst) {
+ assert(0 && "Passed first decl twice, invalid redecl chain!");
+ Current = nullptr;
+ return *this;
+ }
+ PassedFirst = true;
+ }
+
+ // Get either previous decl or latest decl.
+ decl_type *Next = Current->getNextRedeclaration();
+ Current = (Next != Starter) ? Next : nullptr;
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ using redecl_range = llvm::iterator_range<redecl_iterator>;
+
+ /// Returns an iterator range for all the redeclarations of the same
+ /// decl. It will iterate at least once (when this decl is the only one).
+ redecl_range redecls() const {
+ return redecl_range(redecl_iterator(const_cast<decl_type *>(
+ static_cast<const decl_type *>(this))),
+ redecl_iterator());
+ }
+
+ redecl_iterator redecls_begin() const { return redecls().begin(); }
+ redecl_iterator redecls_end() const { return redecls().end(); }
+};
+
+/// Get the primary declaration for a declaration from an AST file. That
+/// will be the first-loaded declaration.
+Decl *getPrimaryMergedDecl(Decl *D);
+
+/// Provides common interface for the Decls that cannot be redeclared,
+/// but can be merged if the same declaration is brought in from multiple
+/// modules.
+template<typename decl_type>
+class Mergeable {
+public:
+ Mergeable() = default;
+
+ /// Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDecl() {
+ auto *D = static_cast<decl_type *>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDecl() const {
+ const auto *D = static_cast<const decl_type *>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// Returns true if this is the first declaration.
+ bool isFirstDecl() const { return getFirstDecl() == this; }
+};
+
+/// A wrapper class around a pointer that always points to its canonical
+/// declaration.
+///
+/// CanonicalDeclPtr<decl_type> behaves just like decl_type*, except we call
+/// decl_type::getCanonicalDecl() on construction.
+///
+/// This is useful for hashtables that you want to be keyed on a declaration's
+/// canonical decl -- if you use CanonicalDeclPtr as the key, you don't need to
+/// remember to call getCanonicalDecl() everywhere.
+template <typename decl_type> class CanonicalDeclPtr {
+public:
+ CanonicalDeclPtr() = default;
+ CanonicalDeclPtr(decl_type *Ptr)
+ : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
+ CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
+ CanonicalDeclPtr &operator=(const CanonicalDeclPtr &) = default;
+
+ operator decl_type *() { return Ptr; }
+ operator const decl_type *() const { return Ptr; }
+
+ decl_type *operator->() { return Ptr; }
+ const decl_type *operator->() const { return Ptr; }
+
+ decl_type &operator*() { return *Ptr; }
+ const decl_type &operator*() const { return *Ptr; }
+
+ friend bool operator==(CanonicalDeclPtr LHS, CanonicalDeclPtr RHS) {
+ return LHS.Ptr == RHS.Ptr;
+ }
+ friend bool operator!=(CanonicalDeclPtr LHS, CanonicalDeclPtr RHS) {
+ return LHS.Ptr != RHS.Ptr;
+ }
+
+private:
+ friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
+ friend struct llvm::PointerLikeTypeTraits<CanonicalDeclPtr<decl_type>>;
+
+ decl_type *Ptr = nullptr;
+};
+
+} // namespace clang
+
+namespace llvm {
+
+template <typename decl_type>
+struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
+ using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
+ using BaseInfo = DenseMapInfo<decl_type *>;
+
+ static CanonicalDeclPtr getEmptyKey() {
+ // Construct our CanonicalDeclPtr this way because the regular constructor
+ // would dereference P.Ptr, which is not allowed.
+ CanonicalDeclPtr P;
+ P.Ptr = BaseInfo::getEmptyKey();
+ return P;
+ }
+
+ static CanonicalDeclPtr getTombstoneKey() {
+ CanonicalDeclPtr P;
+ P.Ptr = BaseInfo::getTombstoneKey();
+ return P;
+ }
+
+ static unsigned getHashValue(const CanonicalDeclPtr &P) {
+ return BaseInfo::getHashValue(P);
+ }
+
+ static bool isEqual(const CanonicalDeclPtr &LHS,
+ const CanonicalDeclPtr &RHS) {
+ return BaseInfo::isEqual(LHS, RHS);
+ }
+};
+
+template <typename decl_type>
+struct PointerLikeTypeTraits<clang::CanonicalDeclPtr<decl_type>> {
+ static inline void *getAsVoidPointer(clang::CanonicalDeclPtr<decl_type> P) {
+ return P.Ptr;
+ }
+ static inline clang::CanonicalDeclPtr<decl_type> getFromVoidPointer(void *P) {
+ clang::CanonicalDeclPtr<decl_type> C;
+ C.Ptr = PointerLikeTypeTraits<decl_type *>::getFromVoidPtr(P);
+ return C;
+ }
+ static constexpr int NumLowBitsAvailable =
+ PointerLikeTypeTraits<decl_type *>::NumLowBitsAvailable;
+};
+
+} // namespace llvm
+
+#endif // LLVM_CLANG_AST_REDECLARABLE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif