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