diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang16/include/clang/AST/Redeclarable.h | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-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.h | 440 |
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 |