| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 1 | //===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// | 
|  | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 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" | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/Optional.h" | 
| Bruno Ricci | cf86ce0 | 2018-09-25 13:43:25 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/PointerIntPair.h" | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 23 |  | 
|  | 24 | namespace clang { | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 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. | 
| Richard Smith | fbe7b46 | 2017-09-22 02:22:32 +0000 | [diff] [blame] | 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; | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 38 |  | 
| Bruno Ricci | cf86ce0 | 2018-09-25 13:43:25 +0000 | [diff] [blame] | 39 | enum { NumLVComputationKindBits = 3 }; | 
|  | 40 |  | 
| Richard Smith | fbe7b46 | 2017-09-22 02:22:32 +0000 | [diff] [blame] | 41 | explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) | 
|  | 42 | : ExplicitKind(EK), IgnoreExplicitVisibility(false), | 
|  | 43 | IgnoreAllVisibility(false) {} | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 44 |  | 
| Richard Smith | fbe7b46 | 2017-09-22 02:22:32 +0000 | [diff] [blame] | 45 | NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { | 
|  | 46 | return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind); | 
|  | 47 | } | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 48 |  | 
| Richard Smith | fbe7b46 | 2017-09-22 02:22:32 +0000 | [diff] [blame] | 49 | bool isTypeVisibility() const { | 
|  | 50 | return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; | 
|  | 51 | } | 
|  | 52 | bool isValueVisibility() const { | 
|  | 53 | return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; | 
|  | 54 | } | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 55 |  | 
|  | 56 | /// Do an LV computation when we only care about the linkage. | 
| Richard Smith | fbe7b46 | 2017-09-22 02:22:32 +0000 | [diff] [blame] | 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 | } | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 71 | }; | 
|  | 72 |  | 
|  | 73 | class LinkageComputer { | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 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>; | 
| George Burgess IV | b8709ba | 2017-08-09 21:20:41 +0000 | [diff] [blame] | 82 | // | 
| Bruno Ricci | cf86ce0 | 2018-09-25 13:43:25 +0000 | [diff] [blame] | 83 | // The integer represents an LVComputationKind. | 
|  | 84 | using QueryType = | 
|  | 85 | llvm::PointerIntPair<const NamedDecl *, | 
|  | 86 | LVComputationKind::NumLVComputationKindBits>; | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 87 | llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; | 
| George Burgess IV | b8709ba | 2017-08-09 21:20:41 +0000 | [diff] [blame] | 88 |  | 
|  | 89 | static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { | 
| Bruno Ricci | cf86ce0 | 2018-09-25 13:43:25 +0000 | [diff] [blame] | 90 | return QueryType(ND, Kind.toBits()); | 
| George Burgess IV | b8709ba | 2017-08-09 21:20:41 +0000 | [diff] [blame] | 91 | } | 
|  | 92 |  | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 93 | llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, | 
|  | 94 | LVComputationKind Kind) const { | 
| George Burgess IV | b8709ba | 2017-08-09 21:20:41 +0000 | [diff] [blame] | 95 | auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 96 | if (Iter == CachedLinkageInfo.end()) | 
|  | 97 | return None; | 
|  | 98 | return Iter->second; | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { | 
| George Burgess IV | b8709ba | 2017-08-09 21:20:41 +0000 | [diff] [blame] | 102 | CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; | 
| George Burgess IV | 35cb4f8 | 2017-08-09 04:12:17 +0000 | [diff] [blame] | 103 | } | 
|  | 104 |  | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 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, | 
| Richard Smith | c95d2c5 | 2017-09-22 04:25:05 +0000 | [diff] [blame] | 124 | LVComputationKind computation, | 
|  | 125 | bool IgnoreVarTypeLinkage); | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 126 |  | 
|  | 127 | LinkageInfo getLVForClassMember(const NamedDecl *D, | 
| Richard Smith | c95d2c5 | 2017-09-22 04:25:05 +0000 | [diff] [blame] | 128 | LVComputationKind computation, | 
|  | 129 | bool IgnoreVarTypeLinkage); | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 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, | 
| Richard Smith | c95d2c5 | 2017-09-22 04:25:05 +0000 | [diff] [blame] | 144 | LVComputationKind computation, | 
|  | 145 | bool IgnoreVarTypeLinkage = false); | 
| George Burgess IV | 99db3ea | 2017-08-09 04:02:49 +0000 | [diff] [blame] | 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 |