1326941Sdim//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// 2326941Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326941Sdim// 7326941Sdim//===----------------------------------------------------------------------===// 8326941Sdim// 9326941Sdim// This file provides AST-internal utilities for linkage and visibility 10326941Sdim// calculation. 11326941Sdim// 12326941Sdim//===----------------------------------------------------------------------===// 13326941Sdim 14326941Sdim#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H 15326941Sdim#define LLVM_CLANG_LIB_AST_LINKAGE_H 16326941Sdim 17326941Sdim#include "clang/AST/Decl.h" 18326941Sdim#include "clang/AST/DeclCXX.h" 19326941Sdim#include "clang/AST/Type.h" 20326941Sdim#include "llvm/ADT/DenseMap.h" 21326941Sdim#include "llvm/ADT/Optional.h" 22344779Sdim#include "llvm/ADT/PointerIntPair.h" 23326941Sdim 24326941Sdimnamespace clang { 25326941Sdim/// Kinds of LV computation. The linkage side of the computation is 26326941Sdim/// always the same, but different things can change how visibility is 27326941Sdim/// computed. 28326941Sdimstruct LVComputationKind { 29326941Sdim /// The kind of entity whose visibility is ultimately being computed; 30326941Sdim /// visibility computations for types and non-types follow different rules. 31326941Sdim unsigned ExplicitKind : 1; 32326941Sdim /// Whether explicit visibility attributes should be ignored. When set, 33326941Sdim /// visibility may only be restricted by the visibility of template arguments. 34326941Sdim unsigned IgnoreExplicitVisibility : 1; 35326941Sdim /// Whether all visibility should be ignored. When set, we're only interested 36326941Sdim /// in computing linkage. 37326941Sdim unsigned IgnoreAllVisibility : 1; 38326941Sdim 39344779Sdim enum { NumLVComputationKindBits = 3 }; 40344779Sdim 41326941Sdim explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK) 42326941Sdim : ExplicitKind(EK), IgnoreExplicitVisibility(false), 43326941Sdim IgnoreAllVisibility(false) {} 44326941Sdim 45326941Sdim NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const { 46326941Sdim return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind); 47326941Sdim } 48326941Sdim 49326941Sdim bool isTypeVisibility() const { 50326941Sdim return getExplicitVisibilityKind() == NamedDecl::VisibilityForType; 51326941Sdim } 52326941Sdim bool isValueVisibility() const { 53326941Sdim return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue; 54326941Sdim } 55326941Sdim 56326941Sdim /// Do an LV computation when we only care about the linkage. 57326941Sdim static LVComputationKind forLinkageOnly() { 58326941Sdim LVComputationKind Result(NamedDecl::VisibilityForValue); 59326941Sdim Result.IgnoreExplicitVisibility = true; 60326941Sdim Result.IgnoreAllVisibility = true; 61326941Sdim return Result; 62326941Sdim } 63326941Sdim 64326941Sdim unsigned toBits() { 65326941Sdim unsigned Bits = 0; 66326941Sdim Bits = (Bits << 1) | ExplicitKind; 67326941Sdim Bits = (Bits << 1) | IgnoreExplicitVisibility; 68326941Sdim Bits = (Bits << 1) | IgnoreAllVisibility; 69326941Sdim return Bits; 70326941Sdim } 71326941Sdim}; 72326941Sdim 73326941Sdimclass LinkageComputer { 74326941Sdim // We have a cache for repeated linkage/visibility computations. This saves us 75326941Sdim // from exponential behavior in heavily templated code, such as: 76326941Sdim // 77326941Sdim // template <typename T, typename V> struct {}; 78326941Sdim // using A = int; 79326941Sdim // using B = Foo<A, A>; 80326941Sdim // using C = Foo<B, B>; 81326941Sdim // using D = Foo<C, C>; 82326941Sdim // 83344779Sdim // The integer represents an LVComputationKind. 84344779Sdim using QueryType = 85344779Sdim llvm::PointerIntPair<const NamedDecl *, 86344779Sdim LVComputationKind::NumLVComputationKindBits>; 87326941Sdim llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; 88326941Sdim 89326941Sdim static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) { 90344779Sdim return QueryType(ND, Kind.toBits()); 91326941Sdim } 92326941Sdim 93326941Sdim llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, 94326941Sdim LVComputationKind Kind) const { 95326941Sdim auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind)); 96326941Sdim if (Iter == CachedLinkageInfo.end()) 97326941Sdim return None; 98326941Sdim return Iter->second; 99326941Sdim } 100326941Sdim 101326941Sdim void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { 102326941Sdim CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info; 103326941Sdim } 104326941Sdim 105326941Sdim LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, 106326941Sdim LVComputationKind computation); 107326941Sdim 108326941Sdim LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, 109326941Sdim LVComputationKind computation); 110326941Sdim 111326941Sdim void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, 112326941Sdim const FunctionTemplateSpecializationInfo *specInfo, 113326941Sdim LVComputationKind computation); 114326941Sdim 115326941Sdim void mergeTemplateLV(LinkageInfo &LV, 116326941Sdim const ClassTemplateSpecializationDecl *spec, 117326941Sdim LVComputationKind computation); 118326941Sdim 119326941Sdim void mergeTemplateLV(LinkageInfo &LV, 120326941Sdim const VarTemplateSpecializationDecl *spec, 121326941Sdim LVComputationKind computation); 122326941Sdim 123326941Sdim LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, 124326941Sdim LVComputationKind computation, 125326941Sdim bool IgnoreVarTypeLinkage); 126326941Sdim 127326941Sdim LinkageInfo getLVForClassMember(const NamedDecl *D, 128326941Sdim LVComputationKind computation, 129326941Sdim bool IgnoreVarTypeLinkage); 130326941Sdim 131326941Sdim LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, 132326941Sdim LVComputationKind computation); 133326941Sdim 134326941Sdim LinkageInfo getLVForLocalDecl(const NamedDecl *D, 135326941Sdim LVComputationKind computation); 136326941Sdim 137326941Sdim LinkageInfo getLVForType(const Type &T, LVComputationKind computation); 138326941Sdim 139326941Sdim LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params, 140326941Sdim LVComputationKind computation); 141326941Sdim 142326941Sdimpublic: 143326941Sdim LinkageInfo computeLVForDecl(const NamedDecl *D, 144326941Sdim LVComputationKind computation, 145326941Sdim bool IgnoreVarTypeLinkage = false); 146326941Sdim 147326941Sdim LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); 148326941Sdim 149326941Sdim LinkageInfo computeTypeLinkageInfo(const Type *T); 150326941Sdim LinkageInfo computeTypeLinkageInfo(QualType T) { 151326941Sdim return computeTypeLinkageInfo(T.getTypePtr()); 152326941Sdim } 153326941Sdim 154326941Sdim LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D); 155326941Sdim 156326941Sdim LinkageInfo getTypeLinkageAndVisibility(const Type *T); 157326941Sdim LinkageInfo getTypeLinkageAndVisibility(QualType T) { 158326941Sdim return getTypeLinkageAndVisibility(T.getTypePtr()); 159326941Sdim } 160326941Sdim}; 161326941Sdim} // namespace clang 162326941Sdim 163326941Sdim#endif 164