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/Optional.h"
23 #include "llvm/ADT/PointerIntPair.h"
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   llvm::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 None;
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