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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file provides AST-internal utilities for linkage and visibility
10// calculation.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
15#define LLVM_CLANG_LIB_AST_LINKAGE_H
16
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 is
27/// always the same, but different things can change how visibility is
28/// 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  unsigned ExplicitKind : 1;
33  /// Whether explicit visibility attributes should be ignored. When set,
34  /// visibility may only be restricted by the visibility of template arguments.
35  unsigned IgnoreExplicitVisibility : 1;
36  /// Whether all visibility should be ignored. When set, we're only interested
37  /// in computing linkage.
38  unsigned IgnoreAllVisibility : 1;
39
40  enum { NumLVComputationKindBits = 3 };
41
42  explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
43      : ExplicitKind(EK), IgnoreExplicitVisibility(false),
44        IgnoreAllVisibility(false) {}
45
46  NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
47    return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
48  }
49
50  bool isTypeVisibility() const {
51    return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
52  }
53  bool isValueVisibility() const {
54    return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
55  }
56
57  /// Do an LV computation when we only care about the linkage.
58  static LVComputationKind forLinkageOnly() {
59    LVComputationKind Result(NamedDecl::VisibilityForValue);
60    Result.IgnoreExplicitVisibility = true;
61    Result.IgnoreAllVisibility = true;
62    return Result;
63  }
64
65  unsigned toBits() {
66    unsigned Bits = 0;
67    Bits = (Bits << 1) | ExplicitKind;
68    Bits = (Bits << 1) | IgnoreExplicitVisibility;
69    Bits = (Bits << 1) | IgnoreAllVisibility;
70    return Bits;
71  }
72};
73
74class LinkageComputer {
75  // We have a cache for repeated linkage/visibility computations. This saves us
76  // from exponential behavior in heavily templated code, such as:
77  //
78  // template <typename T, typename V> struct {};
79  // using A = int;
80  // using B = Foo<A, A>;
81  // using C = Foo<B, B>;
82  // using D = Foo<C, C>;
83  //
84  // The integer represents an LVComputationKind.
85  using QueryType =
86      llvm::PointerIntPair<const NamedDecl *,
87                           LVComputationKind::NumLVComputationKindBits>;
88  llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
89
90  static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
91    return QueryType(ND, Kind.toBits());
92  }
93
94  std::optional<LinkageInfo> lookup(const NamedDecl *ND,
95                                    LVComputationKind Kind) const {
96    auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
97    if (Iter == CachedLinkageInfo.end())
98      return std::nullopt;
99    return Iter->second;
100  }
101
102  void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
103    CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
104  }
105
106  LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
107                                           LVComputationKind computation);
108
109  LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
110                                           LVComputationKind computation);
111
112  void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
113                       const FunctionTemplateSpecializationInfo *specInfo,
114                       LVComputationKind computation);
115
116  void mergeTemplateLV(LinkageInfo &LV,
117                       const ClassTemplateSpecializationDecl *spec,
118                       LVComputationKind computation);
119
120  void mergeTemplateLV(LinkageInfo &LV,
121                       const VarTemplateSpecializationDecl *spec,
122                       LVComputationKind computation);
123
124  LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
125                                         LVComputationKind computation,
126                                         bool IgnoreVarTypeLinkage);
127
128  LinkageInfo getLVForClassMember(const NamedDecl *D,
129                                  LVComputationKind computation,
130                                  bool IgnoreVarTypeLinkage);
131
132  LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
133                              LVComputationKind computation);
134
135  LinkageInfo getLVForLocalDecl(const NamedDecl *D,
136                                LVComputationKind computation);
137
138  LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
139
140  LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
141                                            LVComputationKind computation);
142
143  LinkageInfo getLVForValue(const APValue &V, LVComputationKind computation);
144
145public:
146  LinkageInfo computeLVForDecl(const NamedDecl *D,
147                               LVComputationKind computation,
148                               bool IgnoreVarTypeLinkage = false);
149
150  LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
151
152  LinkageInfo computeTypeLinkageInfo(const Type *T);
153  LinkageInfo computeTypeLinkageInfo(QualType T) {
154    return computeTypeLinkageInfo(T.getTypePtr());
155  }
156
157  LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
158
159  LinkageInfo getTypeLinkageAndVisibility(const Type *T);
160  LinkageInfo getTypeLinkageAndVisibility(QualType T) {
161    return getTypeLinkageAndVisibility(T.getTypePtr());
162  }
163};
164} // namespace clang
165
166#endif
167