xref: /freebsd/contrib/llvm-project/clang/lib/AST/Linkage.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides AST-internal utilities for linkage and visibility
100b57cec5SDimitry Andric // calculation.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LIB_AST_LINKAGE_H
160b57cec5SDimitry Andric 
175ffd83dbSDimitry Andric #include "clang/AST/ASTFwd.h"
180b57cec5SDimitry Andric #include "clang/AST/Decl.h"
190b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/Type.h"
210b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
220b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
23bdd1243dSDimitry Andric #include <optional>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace clang {
260b57cec5SDimitry Andric /// Kinds of LV computation.  The linkage side of the computation is
270b57cec5SDimitry Andric /// always the same, but different things can change how visibility is
280b57cec5SDimitry Andric /// computed.
290b57cec5SDimitry Andric struct LVComputationKind {
300b57cec5SDimitry Andric   /// The kind of entity whose visibility is ultimately being computed;
310b57cec5SDimitry Andric   /// visibility computations for types and non-types follow different rules.
32*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
330b57cec5SDimitry Andric   unsigned ExplicitKind : 1;
340b57cec5SDimitry Andric   /// Whether explicit visibility attributes should be ignored. When set,
350b57cec5SDimitry Andric   /// visibility may only be restricted by the visibility of template arguments.
36*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
370b57cec5SDimitry Andric   unsigned IgnoreExplicitVisibility : 1;
380b57cec5SDimitry Andric   /// Whether all visibility should be ignored. When set, we're only interested
390b57cec5SDimitry Andric   /// in computing linkage.
40*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
410b57cec5SDimitry Andric   unsigned IgnoreAllVisibility : 1;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   enum { NumLVComputationKindBits = 3 };
440b57cec5SDimitry Andric 
LVComputationKindLVComputationKind450b57cec5SDimitry Andric   explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
460b57cec5SDimitry Andric       : ExplicitKind(EK), IgnoreExplicitVisibility(false),
470b57cec5SDimitry Andric         IgnoreAllVisibility(false) {}
480b57cec5SDimitry Andric 
getExplicitVisibilityKindLVComputationKind490b57cec5SDimitry Andric   NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
500b57cec5SDimitry Andric     return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
isTypeVisibilityLVComputationKind530b57cec5SDimitry Andric   bool isTypeVisibility() const {
540b57cec5SDimitry Andric     return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
550b57cec5SDimitry Andric   }
isValueVisibilityLVComputationKind560b57cec5SDimitry Andric   bool isValueVisibility() const {
570b57cec5SDimitry Andric     return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   /// Do an LV computation when we only care about the linkage.
forLinkageOnlyLVComputationKind610b57cec5SDimitry Andric   static LVComputationKind forLinkageOnly() {
620b57cec5SDimitry Andric     LVComputationKind Result(NamedDecl::VisibilityForValue);
630b57cec5SDimitry Andric     Result.IgnoreExplicitVisibility = true;
640b57cec5SDimitry Andric     Result.IgnoreAllVisibility = true;
650b57cec5SDimitry Andric     return Result;
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
toBitsLVComputationKind680b57cec5SDimitry Andric   unsigned toBits() {
690b57cec5SDimitry Andric     unsigned Bits = 0;
700b57cec5SDimitry Andric     Bits = (Bits << 1) | ExplicitKind;
710b57cec5SDimitry Andric     Bits = (Bits << 1) | IgnoreExplicitVisibility;
720b57cec5SDimitry Andric     Bits = (Bits << 1) | IgnoreAllVisibility;
730b57cec5SDimitry Andric     return Bits;
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric class LinkageComputer {
780b57cec5SDimitry Andric   // We have a cache for repeated linkage/visibility computations. This saves us
790b57cec5SDimitry Andric   // from exponential behavior in heavily templated code, such as:
800b57cec5SDimitry Andric   //
810b57cec5SDimitry Andric   // template <typename T, typename V> struct {};
820b57cec5SDimitry Andric   // using A = int;
830b57cec5SDimitry Andric   // using B = Foo<A, A>;
840b57cec5SDimitry Andric   // using C = Foo<B, B>;
850b57cec5SDimitry Andric   // using D = Foo<C, C>;
860b57cec5SDimitry Andric   //
870b57cec5SDimitry Andric   // The integer represents an LVComputationKind.
880b57cec5SDimitry Andric   using QueryType =
890b57cec5SDimitry Andric       llvm::PointerIntPair<const NamedDecl *,
900b57cec5SDimitry Andric                            LVComputationKind::NumLVComputationKindBits>;
910b57cec5SDimitry Andric   llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
920b57cec5SDimitry Andric 
makeCacheKey(const NamedDecl * ND,LVComputationKind Kind)930b57cec5SDimitry Andric   static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
940b57cec5SDimitry Andric     return QueryType(ND, Kind.toBits());
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
lookup(const NamedDecl * ND,LVComputationKind Kind)97bdd1243dSDimitry Andric   std::optional<LinkageInfo> lookup(const NamedDecl *ND,
980b57cec5SDimitry Andric                                     LVComputationKind Kind) const {
990b57cec5SDimitry Andric     auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
1000b57cec5SDimitry Andric     if (Iter == CachedLinkageInfo.end())
101bdd1243dSDimitry Andric       return std::nullopt;
1020b57cec5SDimitry Andric     return Iter->second;
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
cache(const NamedDecl * ND,LVComputationKind Kind,LinkageInfo Info)1050b57cec5SDimitry Andric   void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
1060b57cec5SDimitry Andric     CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
1100b57cec5SDimitry Andric                                            LVComputationKind computation);
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
1130b57cec5SDimitry Andric                                            LVComputationKind computation);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
1160b57cec5SDimitry Andric                        const FunctionTemplateSpecializationInfo *specInfo,
1170b57cec5SDimitry Andric                        LVComputationKind computation);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   void mergeTemplateLV(LinkageInfo &LV,
1200b57cec5SDimitry Andric                        const ClassTemplateSpecializationDecl *spec,
1210b57cec5SDimitry Andric                        LVComputationKind computation);
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   void mergeTemplateLV(LinkageInfo &LV,
1240b57cec5SDimitry Andric                        const VarTemplateSpecializationDecl *spec,
1250b57cec5SDimitry Andric                        LVComputationKind computation);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
1280b57cec5SDimitry Andric                                          LVComputationKind computation,
1290b57cec5SDimitry Andric                                          bool IgnoreVarTypeLinkage);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   LinkageInfo getLVForClassMember(const NamedDecl *D,
1320b57cec5SDimitry Andric                                   LVComputationKind computation,
1330b57cec5SDimitry Andric                                   bool IgnoreVarTypeLinkage);
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
1360b57cec5SDimitry Andric                               LVComputationKind computation);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   LinkageInfo getLVForLocalDecl(const NamedDecl *D,
1390b57cec5SDimitry Andric                                 LVComputationKind computation);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
1440b57cec5SDimitry Andric                                             LVComputationKind computation);
1450b57cec5SDimitry Andric 
146e8d8bef9SDimitry Andric   LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation);
147e8d8bef9SDimitry Andric 
1480b57cec5SDimitry Andric public:
1490b57cec5SDimitry Andric   LinkageInfo computeLVForDecl(const NamedDecl *D,
1500b57cec5SDimitry Andric                                LVComputationKind computation,
1510b57cec5SDimitry Andric                                bool IgnoreVarTypeLinkage = false);
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   LinkageInfo computeTypeLinkageInfo(const Type *T);
computeTypeLinkageInfo(QualType T)1560b57cec5SDimitry Andric   LinkageInfo computeTypeLinkageInfo(QualType T) {
1570b57cec5SDimitry Andric     return computeTypeLinkageInfo(T.getTypePtr());
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   LinkageInfo getTypeLinkageAndVisibility(const Type *T);
getTypeLinkageAndVisibility(QualType T)1630b57cec5SDimitry Andric   LinkageInfo getTypeLinkageAndVisibility(QualType T) {
1640b57cec5SDimitry Andric     return getTypeLinkageAndVisibility(T.getTypePtr());
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric };
1670b57cec5SDimitry Andric } // namespace clang
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric #endif
170