1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
//===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides AST-internal utilities for linkage and visibility
// calculation.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_AST_LINKAGE_H
#define LLVM_CLANG_LIB_AST_LINKAGE_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
namespace clang {
enum : unsigned {
IgnoreExplicitVisibilityBit = 2,
IgnoreAllVisibilityBit = 4
};
/// Kinds of LV computation. The linkage side of the computation is
/// always the same, but different things can change how visibility is
/// computed.
enum LVComputationKind {
/// Do an LV computation for, ultimately, a type.
/// Visibility may be restricted by type visibility settings and
/// the visibility of template arguments.
LVForType = NamedDecl::VisibilityForType,
/// Do an LV computation for, ultimately, a non-type declaration.
/// Visibility may be restricted by value visibility settings and
/// the visibility of template arguments.
LVForValue = NamedDecl::VisibilityForValue,
/// Do an LV computation for, ultimately, a type that already has
/// some sort of explicit visibility. Visibility may only be
/// restricted by the visibility of template arguments.
LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit),
/// Do an LV computation for, ultimately, a non-type declaration
/// that already has some sort of explicit visibility. Visibility
/// may only be restricted by the visibility of template arguments.
LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit),
/// Do an LV computation when we only care about the linkage.
LVForLinkageOnly =
LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit
};
class LinkageComputer {
// We have a cache for repeated linkage/visibility computations. This saves us
// from exponential behavior in heavily templated code, such as:
//
// template <typename T, typename V> struct {};
// using A = int;
// using B = Foo<A, A>;
// using C = Foo<B, B>;
// using D = Foo<C, C>;
//
// Note that the unsigned is actually a LVComputationKind; ubsan's enum
// sanitizer doesn't like tombstone/empty markers outside of
// LVComputationKind's range.
using QueryType = std::pair<const NamedDecl *, unsigned>;
llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
return std::make_pair(ND, static_cast<unsigned>(Kind));
}
llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
LVComputationKind Kind) const {
auto Iter = CachedLinkageInfo.find(makeCacheKey(ND, Kind));
if (Iter == CachedLinkageInfo.end())
return None;
return Iter->second;
}
void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) {
CachedLinkageInfo[makeCacheKey(ND, Kind)] = Info;
}
LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LVComputationKind computation);
LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
LVComputationKind computation);
void mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn,
const FunctionTemplateSpecializationInfo *specInfo,
LVComputationKind computation);
void mergeTemplateLV(LinkageInfo &LV,
const ClassTemplateSpecializationDecl *spec,
LVComputationKind computation);
void mergeTemplateLV(LinkageInfo &LV,
const VarTemplateSpecializationDecl *spec,
LVComputationKind computation);
LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation);
LinkageInfo getLVForClassMember(const NamedDecl *D,
LVComputationKind computation);
LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
LVComputationKind computation);
LinkageInfo getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation);
LinkageInfo getLVForType(const Type &T, LVComputationKind computation);
LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params,
LVComputationKind computation);
public:
LinkageInfo computeLVForDecl(const NamedDecl *D,
LVComputationKind computation);
LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation);
LinkageInfo computeTypeLinkageInfo(const Type *T);
LinkageInfo computeTypeLinkageInfo(QualType T) {
return computeTypeLinkageInfo(T.getTypePtr());
}
LinkageInfo getDeclLinkageAndVisibility(const NamedDecl *D);
LinkageInfo getTypeLinkageAndVisibility(const Type *T);
LinkageInfo getTypeLinkageAndVisibility(QualType T) {
return getTypeLinkageAndVisibility(T.getTypePtr());
}
};
} // namespace clang
#endif
|