| //===----- Linkage.h - Linkage calculation-related utilities ----*- 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 provides AST-internal utilities for linkage and visibility | 
 | // calculation. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H | 
 | #define LLVM_CLANG_LIB_AST_LINKAGE_H | 
 |  | 
 | #include "clang/AST/ASTFwd.h" | 
 | #include "clang/AST/Decl.h" | 
 | #include "clang/AST/DeclCXX.h" | 
 | #include "clang/AST/Type.h" | 
 | #include "llvm/ADT/DenseMap.h" | 
 | #include "llvm/ADT/PointerIntPair.h" | 
 | #include <optional> | 
 |  | 
 | namespace clang { | 
 | /// Kinds of LV computation.  The linkage side of the computation is | 
 | /// always the same, but different things can change how visibility is | 
 | /// computed. | 
 | struct LVComputationKind { | 
 |   /// The kind of entity whose visibility is ultimately being computed; | 
 |   /// visibility computations for types and non-types follow different rules. | 
 |   LLVM_PREFERRED_TYPE(bool) | 
 |   unsigned ExplicitKind : 1; | 
 |   /// Whether explicit visibility attributes should be ignored. When set, | 
 |   /// visibility may only be restricted by the visibility of template arguments. | 
 |   LLVM_PREFERRED_TYPE(bool) | 
 |   unsigned IgnoreExplicitVisibility : 1; | 
 |   /// Whether all visibility should be ignored. When set, we're only interested | 
 |   /// in computing linkage. | 
 |   LLVM_PREFERRED_TYPE(bool) | 
 |   unsigned IgnoreAllVisibility : 1; | 
 |  | 
 |   static constexpr int NumLVComputationKindBits = 3; | 
 |  | 
 |   explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) | 
 |       : ExplicitKind(EK), IgnoreExplicitVisibility(false), | 
 |         IgnoreAllVisibility(false) {} | 
 |  | 
 |   NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { | 
 |     return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind); | 
 |   } | 
 |  | 
 |   bool isTypeVisibility() const { | 
 |     return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; | 
 |   } | 
 |   bool isValueVisibility() const { | 
 |     return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; | 
 |   } | 
 |  | 
 |   /// Do an LV computation when we only care about the linkage. | 
 |   static LVComputationKind forLinkageOnly() { | 
 |     LVComputationKind Result(NamedDecl::VisibilityForValue); | 
 |     Result.IgnoreExplicitVisibility = true; | 
 |     Result.IgnoreAllVisibility = true; | 
 |     return Result; | 
 |   } | 
 |  | 
 |   unsigned toBits() { | 
 |     unsigned Bits = 0; | 
 |     Bits = (Bits << 1) | ExplicitKind; | 
 |     Bits = (Bits << 1) | IgnoreExplicitVisibility; | 
 |     Bits = (Bits << 1) | IgnoreAllVisibility; | 
 |     return Bits; | 
 |   } | 
 | }; | 
 |  | 
 | class LinkageComputer { | 
 |   // We have a cache for repeated linkage/visibility computations. This saves us | 
 |   // from exponential behavior in heavily templated code, such as: | 
 |   // | 
 |   // template <typename T, typename V> struct {}; | 
 |   // using A = int; | 
 |   // using B = Foo<A, A>; | 
 |   // using C = Foo<B, B>; | 
 |   // using D = Foo<C, C>; | 
 |   // | 
 |   // The integer represents an LVComputationKind. | 
 |   using QueryType = | 
 |       llvm::PointerIntPair<const NamedDecl *, | 
 |                            LVComputationKind::NumLVComputationKindBits>; | 
 |   llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; | 
 |  | 
 |   static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { | 
 |     return QueryType(ND, Kind.toBits()); | 
 |   } | 
 |  | 
 |   std::optional<LinkageInfo> lookup(const NamedDecl *ND, | 
 |                                     LVComputationKind Kind) const { | 
 |     auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); | 
 |     if (Iter == CachedLinkageInfo.end()) | 
 |       return std::nullopt; | 
 |     return Iter->second; | 
 |   } | 
 |  | 
 |   void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { | 
 |     CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; | 
 |   } | 
 |  | 
 |   LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, | 
 |                                            LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, | 
 |                                            LVComputationKind computation); | 
 |  | 
 |   void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, | 
 |                        const FunctionTemplateSpecializationInfo *specInfo, | 
 |                        LVComputationKind computation); | 
 |  | 
 |   void mergeTemplateLV(LinkageInfo &LV, | 
 |                        const ClassTemplateSpecializationDecl *spec, | 
 |                        LVComputationKind computation); | 
 |  | 
 |   void mergeTemplateLV(LinkageInfo &LV, | 
 |                        const VarTemplateSpecializationDecl *spec, | 
 |                        LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, | 
 |                                          LVComputationKind computation, | 
 |                                          bool IgnoreVarTypeLinkage); | 
 |  | 
 |   LinkageInfo getLVForClassMember(const NamedDecl *D, | 
 |                                   LVComputationKind computation, | 
 |                                   bool IgnoreVarTypeLinkage); | 
 |  | 
 |   LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, | 
 |                               LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForLocalDecl(const NamedDecl *D, | 
 |                                 LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForType(const Type &T, LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params, | 
 |                                             LVComputationKind computation); | 
 |  | 
 |   LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation); | 
 |  | 
 | public: | 
 |   LinkageInfo computeLVForDecl(const NamedDecl *D, | 
 |                                LVComputationKind computation, | 
 |                                bool IgnoreVarTypeLinkage = false); | 
 |  | 
 |   LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); | 
 |  | 
 |   LinkageInfo computeTypeLinkageInfo(const Type *T); | 
 |   LinkageInfo computeTypeLinkageInfo(QualType T) { | 
 |     return computeTypeLinkageInfo(T.getTypePtr()); | 
 |   } | 
 |  | 
 |   LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D); | 
 |  | 
 |   LinkageInfo getTypeLinkageAndVisibility(const Type *T); | 
 |   LinkageInfo getTypeLinkageAndVisibility(QualType T) { | 
 |     return getTypeLinkageAndVisibility(T.getTypePtr()); | 
 |   } | 
 | }; | 
 | } // namespace clang | 
 |  | 
 | #endif |