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