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