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