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