| //===----- 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/Decl.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/Type.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/PointerIntPair.h" |
| |
| 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. |
| unsigned ExplicitKind : 1; |
| /// Whether explicit visibility attributes should be ignored. When set, |
| /// visibility may only be restricted by the visibility of template arguments. |
| unsigned IgnoreExplicitVisibility : 1; |
| /// Whether all visibility should be ignored. When set, we're only interested |
| /// in computing linkage. |
| unsigned IgnoreAllVisibility : 1; |
| |
| enum { NumLVComputationKindBits = 3 }; |
| |
| explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) |
| : ExplicitKind(EK), IgnoreExplicitVisibility(false), |
| IgnoreAllVisibility(false) {} |
| |
| NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { |
| return static_cast<NamedDecl::ExplicitVisibilityKind>(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 <typename T, typename V> struct {}; |
| // using A = int; |
| // using B = Foo<A, A>; |
| // using C = Foo<B, B>; |
| // using D = Foo<C, C>; |
| // |
| // The integer represents an LVComputationKind. |
| using QueryType = |
| llvm::PointerIntPair<const NamedDecl *, |
| LVComputationKind::NumLVComputationKindBits>; |
| llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; |
| |
| static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { |
| return QueryType(ND, Kind.toBits()); |
| } |
| |
| llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, |
| LVComputationKind Kind) const { |
| auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); |
| if (Iter == CachedLinkageInfo.end()) |
| return None; |
| return Iter->second; |
| } |
| |
| void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { |
| CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; |
| } |
| |
| LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> 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); |
| |
| 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 |