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