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