xref: /openbsd-src/gnu/llvm/clang/lib/AST/Linkage.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file provides AST-internal utilities for linkage and visibility
10e5dd7070Spatrick // calculation.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
15e5dd7070Spatrick #define LLVM_CLANG_LIB_AST_LINKAGE_H
16e5dd7070Spatrick 
17ec727ea7Spatrick #include "clang/AST/ASTFwd.h"
18e5dd7070Spatrick #include "clang/AST/Decl.h"
19e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
20e5dd7070Spatrick #include "clang/AST/Type.h"
21e5dd7070Spatrick #include "llvm/ADT/DenseMap.h"
22e5dd7070Spatrick #include "llvm/ADT/PointerIntPair.h"
23*12c85518Srobert #include <optional>
24e5dd7070Spatrick 
25e5dd7070Spatrick namespace clang {
26e5dd7070Spatrick /// Kinds of LV computation.  The linkage side of the computation is
27e5dd7070Spatrick /// always the same, but different things can change how visibility is
28e5dd7070Spatrick /// computed.
29e5dd7070Spatrick struct LVComputationKind {
30e5dd7070Spatrick   /// The kind of entity whose visibility is ultimately being computed;
31e5dd7070Spatrick   /// visibility computations for types and non-types follow different rules.
32e5dd7070Spatrick   unsigned ExplicitKind : 1;
33e5dd7070Spatrick   /// Whether explicit visibility attributes should be ignored. When set,
34e5dd7070Spatrick   /// visibility may only be restricted by the visibility of template arguments.
35e5dd7070Spatrick   unsigned IgnoreExplicitVisibility : 1;
36e5dd7070Spatrick   /// Whether all visibility should be ignored. When set, we're only interested
37e5dd7070Spatrick   /// in computing linkage.
38e5dd7070Spatrick   unsigned IgnoreAllVisibility : 1;
39e5dd7070Spatrick 
40e5dd7070Spatrick   enum { NumLVComputationKindBits = 3 };
41e5dd7070Spatrick 
LVComputationKindLVComputationKind42e5dd7070Spatrick   explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
43e5dd7070Spatrick       : ExplicitKind(EK), IgnoreExplicitVisibility(false),
44e5dd7070Spatrick         IgnoreAllVisibility(false) {}
45e5dd7070Spatrick 
getExplicitVisibilityKindLVComputationKind46e5dd7070Spatrick   NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
47e5dd7070Spatrick     return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
48e5dd7070Spatrick   }
49e5dd7070Spatrick 
isTypeVisibilityLVComputationKind50e5dd7070Spatrick   bool isTypeVisibility() const {
51e5dd7070Spatrick     return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
52e5dd7070Spatrick   }
isValueVisibilityLVComputationKind53e5dd7070Spatrick   bool isValueVisibility() const {
54e5dd7070Spatrick     return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
55e5dd7070Spatrick   }
56e5dd7070Spatrick 
57e5dd7070Spatrick   /// Do an LV computation when we only care about the linkage.
forLinkageOnlyLVComputationKind58e5dd7070Spatrick   static LVComputationKind forLinkageOnly() {
59e5dd7070Spatrick     LVComputationKind Result(NamedDecl::VisibilityForValue);
60e5dd7070Spatrick     Result.IgnoreExplicitVisibility = true;
61e5dd7070Spatrick     Result.IgnoreAllVisibility = true;
62e5dd7070Spatrick     return Result;
63e5dd7070Spatrick   }
64e5dd7070Spatrick 
toBitsLVComputationKind65e5dd7070Spatrick   unsigned toBits() {
66e5dd7070Spatrick     unsigned Bits = 0;
67e5dd7070Spatrick     Bits = (Bits << 1) | ExplicitKind;
68e5dd7070Spatrick     Bits = (Bits << 1) | IgnoreExplicitVisibility;
69e5dd7070Spatrick     Bits = (Bits << 1) | IgnoreAllVisibility;
70e5dd7070Spatrick     return Bits;
71e5dd7070Spatrick   }
72e5dd7070Spatrick };
73e5dd7070Spatrick 
74e5dd7070Spatrick class LinkageComputer {
75e5dd7070Spatrick   // We have a cache for repeated linkage/visibility computations. This saves us
76e5dd7070Spatrick   // from exponential behavior in heavily templated code, such as:
77e5dd7070Spatrick   //
78e5dd7070Spatrick   // template <typename T, typename V> struct {};
79e5dd7070Spatrick   // using A = int;
80e5dd7070Spatrick   // using B = Foo<A, A>;
81e5dd7070Spatrick   // using C = Foo<B, B>;
82e5dd7070Spatrick   // using D = Foo<C, C>;
83e5dd7070Spatrick   //
84e5dd7070Spatrick   // The integer represents an LVComputationKind.
85e5dd7070Spatrick   using QueryType =
86e5dd7070Spatrick       llvm::PointerIntPair<const NamedDecl *,
87e5dd7070Spatrick                            LVComputationKind::NumLVComputationKindBits>;
88e5dd7070Spatrick   llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
89e5dd7070Spatrick 
makeCacheKey(const NamedDecl * ND,LVComputationKind Kind)90e5dd7070Spatrick   static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
91e5dd7070Spatrick     return QueryType(ND, Kind.toBits());
92e5dd7070Spatrick   }
93e5dd7070Spatrick 
lookup(const NamedDecl * ND,LVComputationKind Kind)94*12c85518Srobert   std::optional<LinkageInfo> lookup(const NamedDecl *ND,
95e5dd7070Spatrick                                     LVComputationKind Kind) const {
96e5dd7070Spatrick     auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
97e5dd7070Spatrick     if (Iter == CachedLinkageInfo.end())
98*12c85518Srobert       return std::nullopt;
99e5dd7070Spatrick     return Iter->second;
100e5dd7070Spatrick   }
101e5dd7070Spatrick 
cache(const NamedDecl * ND,LVComputationKind Kind,LinkageInfo Info)102e5dd7070Spatrick   void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
103e5dd7070Spatrick     CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
104e5dd7070Spatrick   }
105e5dd7070Spatrick 
106e5dd7070Spatrick   LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
107e5dd7070Spatrick                                            LVComputationKind computation);
108e5dd7070Spatrick 
109e5dd7070Spatrick   LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
110e5dd7070Spatrick                                            LVComputationKind computation);
111e5dd7070Spatrick 
112e5dd7070Spatrick   void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
113e5dd7070Spatrick                        const FunctionTemplateSpecializationInfo *specInfo,
114e5dd7070Spatrick                        LVComputationKind computation);
115e5dd7070Spatrick 
116e5dd7070Spatrick   void mergeTemplateLV(LinkageInfo &LV,
117e5dd7070Spatrick                        const ClassTemplateSpecializationDecl *spec,
118e5dd7070Spatrick                        LVComputationKind computation);
119e5dd7070Spatrick 
120e5dd7070Spatrick   void mergeTemplateLV(LinkageInfo &LV,
121e5dd7070Spatrick                        const VarTemplateSpecializationDecl *spec,
122e5dd7070Spatrick                        LVComputationKind computation);
123e5dd7070Spatrick 
124e5dd7070Spatrick   LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
125e5dd7070Spatrick                                          LVComputationKind computation,
126e5dd7070Spatrick                                          bool IgnoreVarTypeLinkage);
127e5dd7070Spatrick 
128e5dd7070Spatrick   LinkageInfo getLVForClassMember(const NamedDecl *D,
129e5dd7070Spatrick                                   LVComputationKind computation,
130e5dd7070Spatrick                                   bool IgnoreVarTypeLinkage);
131e5dd7070Spatrick 
132e5dd7070Spatrick   LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
133e5dd7070Spatrick                               LVComputationKind computation);
134e5dd7070Spatrick 
135e5dd7070Spatrick   LinkageInfo getLVForLocalDecl(const NamedDecl *D,
136e5dd7070Spatrick                                 LVComputationKind computation);
137e5dd7070Spatrick 
138e5dd7070Spatrick   LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
139e5dd7070Spatrick 
140e5dd7070Spatrick   LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
141e5dd7070Spatrick                                             LVComputationKind computation);
142e5dd7070Spatrick 
143a9ac8606Spatrick   LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation);
144a9ac8606Spatrick 
145e5dd7070Spatrick public:
146e5dd7070Spatrick   LinkageInfo computeLVForDecl(const NamedDecl *D,
147e5dd7070Spatrick                                LVComputationKind computation,
148e5dd7070Spatrick                                bool IgnoreVarTypeLinkage = false);
149e5dd7070Spatrick 
150e5dd7070Spatrick   LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
151e5dd7070Spatrick 
152e5dd7070Spatrick   LinkageInfo computeTypeLinkageInfo(const Type *T);
computeTypeLinkageInfo(QualType T)153e5dd7070Spatrick   LinkageInfo computeTypeLinkageInfo(QualType T) {
154e5dd7070Spatrick     return computeTypeLinkageInfo(T.getTypePtr());
155e5dd7070Spatrick   }
156e5dd7070Spatrick 
157e5dd7070Spatrick   LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
158e5dd7070Spatrick 
159e5dd7070Spatrick   LinkageInfo getTypeLinkageAndVisibility(const Type *T);
getTypeLinkageAndVisibility(QualType T)160e5dd7070Spatrick   LinkageInfo getTypeLinkageAndVisibility(QualType T) {
161e5dd7070Spatrick     return getTypeLinkageAndVisibility(T.getTypePtr());
162e5dd7070Spatrick   }
163e5dd7070Spatrick };
164e5dd7070Spatrick } // namespace clang
165e5dd7070Spatrick 
166e5dd7070Spatrick #endif
167