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