1 //===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file provides AST-internal utilities for linkage and visibility 10 // calculation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H 15 #define LLVM_CLANG_LIB_AST_LINKAGE_H 16 17 #include "clang/AST/ASTFwd.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/DeclCXX.h" 20 #include "clang/AST/Type.h" 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ADT/PointerIntPair.h" 23 #include <optional> 24 25 namespace clang { 26 /// Kinds of LV computation. The linkage side of the computation is 27 /// always the same, but different things can change how visibility is 28 /// computed. 29 struct LVComputationKind { 30 /// The kind of entity whose visibility is ultimately being computed; 31 /// visibility computations for types and non-types follow different rules. 32 LLVM_PREFERRED_TYPE(bool) 33 unsigned ExplicitKind : 1; 34 /// Whether explicit visibility attributes should be ignored. When set, 35 /// visibility may only be restricted by the visibility of template arguments. 36 LLVM_PREFERRED_TYPE(bool) 37 unsigned IgnoreExplicitVisibility : 1; 38 /// Whether all visibility should be ignored. When set, we're only interested 39 /// in computing linkage. 40 LLVM_PREFERRED_TYPE(bool) 41 unsigned IgnoreAllVisibility : 1; 42 43 enum { NumLVComputationKindBits = 3 }; 44 LVComputationKindLVComputationKind45 explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) 46 : ExplicitKind(EK), IgnoreExplicitVisibility(false), 47 IgnoreAllVisibility(false) {} 48 getExplicitVisibilityKindLVComputationKind49 NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { 50 return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind); 51 } 52 isTypeVisibilityLVComputationKind53 bool isTypeVisibility() const { 54 return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; 55 } isValueVisibilityLVComputationKind56 bool isValueVisibility() const { 57 return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; 58 } 59 60 /// Do an LV computation when we only care about the linkage. forLinkageOnlyLVComputationKind61 static LVComputationKind forLinkageOnly() { 62 LVComputationKind Result(NamedDecl::VisibilityForValue); 63 Result.IgnoreExplicitVisibility = true; 64 Result.IgnoreAllVisibility = true; 65 return Result; 66 } 67 toBitsLVComputationKind68 unsigned toBits() { 69 unsigned Bits = 0; 70 Bits = (Bits << 1) | ExplicitKind; 71 Bits = (Bits << 1) | IgnoreExplicitVisibility; 72 Bits = (Bits << 1) | IgnoreAllVisibility; 73 return Bits; 74 } 75 }; 76 77 class LinkageComputer { 78 // We have a cache for repeated linkage/visibility computations. This saves us 79 // from exponential behavior in heavily templated code, such as: 80 // 81 // template <typename T, typename V> struct {}; 82 // using A = int; 83 // using B = Foo<A, A>; 84 // using C = Foo<B, B>; 85 // using D = Foo<C, C>; 86 // 87 // The integer represents an LVComputationKind. 88 using QueryType = 89 llvm::PointerIntPair<const NamedDecl *, 90 LVComputationKind::NumLVComputationKindBits>; 91 llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; 92 makeCacheKey(const NamedDecl * ND,LVComputationKind Kind)93 static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { 94 return QueryType(ND, Kind.toBits()); 95 } 96 lookup(const NamedDecl * ND,LVComputationKind Kind)97 std::optional<LinkageInfo> lookup(const NamedDecl *ND, 98 LVComputationKind Kind) const { 99 auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); 100 if (Iter == CachedLinkageInfo.end()) 101 return std::nullopt; 102 return Iter->second; 103 } 104 cache(const NamedDecl * ND,LVComputationKind Kind,LinkageInfo Info)105 void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { 106 CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; 107 } 108 109 LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, 110 LVComputationKind computation); 111 112 LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, 113 LVComputationKind computation); 114 115 void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, 116 const FunctionTemplateSpecializationInfo *specInfo, 117 LVComputationKind computation); 118 119 void mergeTemplateLV(LinkageInfo &LV, 120 const ClassTemplateSpecializationDecl *spec, 121 LVComputationKind computation); 122 123 void mergeTemplateLV(LinkageInfo &LV, 124 const VarTemplateSpecializationDecl *spec, 125 LVComputationKind computation); 126 127 LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, 128 LVComputationKind computation, 129 bool IgnoreVarTypeLinkage); 130 131 LinkageInfo getLVForClassMember(const NamedDecl *D, 132 LVComputationKind computation, 133 bool IgnoreVarTypeLinkage); 134 135 LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, 136 LVComputationKind computation); 137 138 LinkageInfo getLVForLocalDecl(const NamedDecl *D, 139 LVComputationKind computation); 140 141 LinkageInfo getLVForType(const Type &T, LVComputationKind computation); 142 143 LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params, 144 LVComputationKind computation); 145 146 LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation); 147 148 public: 149 LinkageInfo computeLVForDecl(const NamedDecl *D, 150 LVComputationKind computation, 151 bool IgnoreVarTypeLinkage = false); 152 153 LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); 154 155 LinkageInfo computeTypeLinkageInfo(const Type *T); computeTypeLinkageInfo(QualType T)156 LinkageInfo computeTypeLinkageInfo(QualType T) { 157 return computeTypeLinkageInfo(T.getTypePtr()); 158 } 159 160 LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D); 161 162 LinkageInfo getTypeLinkageAndVisibility(const Type *T); getTypeLinkageAndVisibility(QualType T)163 LinkageInfo getTypeLinkageAndVisibility(QualType T) { 164 return getTypeLinkageAndVisibility(T.getTypePtr()); 165 } 166 }; 167 } // namespace clang 168 169 #endif 170