//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file provides AST-internal utilities for linkage and visibility // calculation. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_AST_LINKAGE_H #define LLVM_CLANG_LIB_AST_LINKAGE_H #include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include namespace clang { /// Kinds of LV computation. The linkage side of the computation is /// always the same, but different things can change how visibility is /// computed. struct LVComputationKind { /// The kind of entity whose visibility is ultimately being computed; /// visibility computations for types and non-types follow different rules. LLVM_PREFERRED_TYPE(bool) unsigned ExplicitKind : 1; /// Whether explicit visibility attributes should be ignored. When set, /// visibility may only be restricted by the visibility of template arguments. LLVM_PREFERRED_TYPE(bool) unsigned IgnoreExplicitVisibility : 1; /// Whether all visibility should be ignored. When set, we're only interested /// in computing linkage. LLVM_PREFERRED_TYPE(bool) unsigned IgnoreAllVisibility : 1; enum { NumLVComputationKindBits = 3 }; explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) : ExplicitKind(EK), IgnoreExplicitVisibility(false), IgnoreAllVisibility(false) {} NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { return static_cast(ExplicitKind); } bool isTypeVisibility() const { return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; } bool isValueVisibility() const { return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; } /// Do an LV computation when we only care about the linkage. static LVComputationKind forLinkageOnly() { LVComputationKind Result(NamedDecl::VisibilityForValue); Result.IgnoreExplicitVisibility = true; Result.IgnoreAllVisibility = true; return Result; } unsigned toBits() { unsigned Bits = 0; Bits = (Bits << 1) | ExplicitKind; Bits = (Bits << 1) | IgnoreExplicitVisibility; Bits = (Bits << 1) | IgnoreAllVisibility; return Bits; } }; class LinkageComputer { // We have a cache for repeated linkage/visibility computations. This saves us // from exponential behavior in heavily templated code, such as: // // template struct {}; // using A = int; // using B = Foo; // using C = Foo; // using D = Foo; // // The integer represents an LVComputationKind. using QueryType = llvm::PointerIntPair; llvm::SmallDenseMap CachedLinkageInfo; static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { return QueryType(ND, Kind.toBits()); } std::optional lookup(const NamedDecl *ND, LVComputationKind Kind) const { auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); if (Iter == CachedLinkageInfo.end()) return std::nullopt; return Iter->second; } void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; } LinkageInfo getLVForTemplateArgumentList(ArrayRef Args, LVComputationKind computation); LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, LVComputationKind computation); void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, const FunctionTemplateSpecializationInfo *specInfo, LVComputationKind computation); void mergeTemplateLV(LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec, LVComputationKind computation); void mergeTemplateLV(LinkageInfo &LV, const VarTemplateSpecializationDecl *spec, LVComputationKind computation); LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation, bool IgnoreVarTypeLinkage); LinkageInfo getLVForClassMember(const NamedDecl *D, LVComputationKind computation, bool IgnoreVarTypeLinkage); LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, LVComputationKind computation); LinkageInfo getLVForLocalDecl(const NamedDecl *D, LVComputationKind computation); LinkageInfo getLVForType(const Type &T, LVComputationKind computation); LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params, LVComputationKind computation); LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation); public: LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation, bool IgnoreVarTypeLinkage = false); LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); LinkageInfo computeTypeLinkageInfo(const Type *T); LinkageInfo computeTypeLinkageInfo(QualType T) { return computeTypeLinkageInfo(T.getTypePtr()); } LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D); LinkageInfo getTypeLinkageAndVisibility(const Type *T); LinkageInfo getTypeLinkageAndVisibility(QualType T) { return getTypeLinkageAndVisibility(T.getTypePtr()); } }; } // namespace clang #endif