clang: lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/DenseSet.h"
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/Casting.h"
17#include
18
22
23namespace {
24
25using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
26
27
28struct SymbolHeaderMapping {
29 llvm::StringRef *HeaderNames = nullptr;
30
31 llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;
32
33 unsigned SymbolCount = 0;
34
35 struct SymbolName {
36 const char *Data;
37 unsigned ScopeLen;
38 unsigned NameLen;
39 StringRef scope() const { return StringRef(Data, ScopeLen); }
40 StringRef name() const { return StringRef(Data + ScopeLen, NameLen); }
41 StringRef qualifiedName() const {
42 return StringRef(Data, ScopeLen + NameLen);
43 }
44 } *SymbolNames = nullptr;
45
46 llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols = nullptr;
47
48 llvm::SmallVector *SymbolHeaderIDs = nullptr;
49};
50}
51static SymbolHeaderMapping
56
59#define SYMBOL(Name, NS, Header) #NS #Name,
62 static constexpr const char *CSymbols[] = {
65 };
66 Symbols = CSymbols;
67 break;
68 }
70 static constexpr const char *CXXSymbols[] = {
74 };
75 Symbols = CXXSymbols;
76 break;
77 }
78 }
79#undef SYMBOL
80 return llvm::DenseSet(llvm::from_range, Symbols).size();
81}
82
84 SymbolHeaderMapping *Mapping = new SymbolHeaderMapping();
86
88 Mapping->SymbolCount = SymCount;
89 Mapping->SymbolNames =
90 new std::remove_reference_t<decltype(*Mapping->SymbolNames)>[SymCount];
91 Mapping->SymbolHeaderIDs = new std::remove_reference_t<
92 decltype(*Mapping->SymbolHeaderIDs)>[SymCount];
93 Mapping->NamespaceSymbols =
94 new std::remove_reference_t<decltype(*Mapping->NamespaceSymbols)>;
95 Mapping->HeaderIDs =
96 new std::remove_reference_t<decltype(*Mapping->HeaderIDs)>;
97 auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {
98 auto R = Mapping->NamespaceSymbols->try_emplace(NS, nullptr);
99 if (R.second)
100 R.first->second = new NSSymbolMap();
101 return *R.first->second;
102 };
103
104 auto AddHeader = [&](llvm::StringRef Header) -> unsigned {
105 return Mapping->HeaderIDs->try_emplace(Header, Mapping->HeaderIDs->size())
106 .first->second;
107 };
108
109 auto Add = [&, SymIndex(-1)](llvm::StringRef QName, unsigned NSLen,
110 llvm::StringRef HeaderName) mutable {
111
112
113 if (QName.take_front(NSLen) == "None") {
114 QName = QName.drop_front(NSLen);
115 NSLen = 0;
116 }
117
118 if (SymIndex > 0) {
119 assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
120 [&QName](const SymbolHeaderMapping::SymbolName &S) {
121 return S.qualifiedName() == QName;
122 }) &&
123 "The symbol has been added before, make sure entries in the .inc "
124 "file are grouped by symbol name!");
125 }
126 if (SymIndex < 0 ||
127 Mapping->SymbolNames[SymIndex].qualifiedName() != QName) {
128
129 ++SymIndex;
130 }
131 Mapping->SymbolNames[SymIndex] = {
132 QName.data(), NSLen, static_cast<unsigned int>(QName.size() - NSLen)};
133 if (!HeaderName.empty())
134 Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));
135
136 NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen));
137 NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex);
138 };
139
141 const char *QName;
142 unsigned NSLen;
143 const char *HeaderName;
144 };
145#define SYMBOL(Name, NS, Header) \
146 {#NS #Name, static_cast<decltype(Symbol::NSLen)>(StringRef(#NS).size()), \
147 #Header},
150 static constexpr Symbol CSymbols[] = {
153 };
154 for (const Symbol &S : CSymbols)
155 Add(S.QName, S.NSLen, S.HeaderName);
156 break;
157 }
159 static constexpr Symbol CXXSymbols[] = {
163 };
164 for (const Symbol &S : CXXSymbols)
165 Add(S.QName, S.NSLen, S.HeaderName);
166 break;
167 }
168 }
169#undef SYMBOL
170
171 Mapping->HeaderNames = new llvm::StringRef[Mapping->HeaderIDs->size()];
172 for (const auto &E : *Mapping->HeaderIDs)
173 Mapping->HeaderNames[E.second] = E.first;
174
175 return 0;
176}
177
179 static int Dummy = []() {
180 for (unsigned L = 0; L <= static_cast(Lang::LastValue); ++L)
182 return 0;
183 }();
184 (void)Dummy;
185}
186
189 std::vector
191 Result.reserve(Mapping->HeaderIDs->size());
192 for (unsigned I = 0, E = Mapping->HeaderIDs->size(); I < E; ++I)
193 Result.push_back(Header(I, L));
195}
199 auto It = Mapping->HeaderIDs->find(Name);
200 if (It == Mapping->HeaderIDs->end())
201 return std::nullopt;
202 return Header(It->second, L);
203}
207
210 std::vector Result;
212 Result.reserve(Mapping->SymbolCount);
213 for (unsigned I = 0, E = Mapping->SymbolCount; I < E; ++I)
214 Result.push_back(Symbol(I, L));
216}
229
230 if (NSSymbolMap *NSSymbols =
232 auto It = NSSymbols->find(Name);
233 if (It != NSSymbols->end())
234 return Symbol(It->second, L);
235 }
236 return std::nullopt;
237}
239 const auto &Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];
240 if (Headers.empty())
241 return std::nullopt;
242 return Header(Headers.front(), Language);
243}
246 for (auto HeaderID : getMappingPerLang(Language)->SymbolHeaderIDs[ID])
247 Results.emplace_back(Header(HeaderID, Language));
248 return Results;
249}
250
252
253NSSymbolMap *Recognizer::namespaceSymbols(const DeclContext *DC, Lang L) {
256
257 auto It = NamespaceCache.find(DC);
258 if (It != NamespaceCache.end())
259 return It->second;
260 const NamespaceDecl *D = llvm::cast(DC);
261 NSSymbolMap *Result = [&]() -> NSSymbolMap * {
263 return nullptr;
264
265 std::string Scope;
266 for (const auto *ND = D; ND;
267 ND = llvm::dyn_cast_or_null(ND->getParent()))
268 if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace())
269 Scope = ND->getName().str() + "::" + Scope;
271 }();
272 NamespaceCache.try_emplace(D, Result);
274}
275
282 else
283 return std::nullopt;
284
285
286
287
290 if (!DC)
291 return std::nullopt;
294 IntermediateDecl.push_back(DC);
296 }
297 NSSymbolMap *Symbols = namespaceSymbols(DC, L);
298 if (!Symbols)
299 return std::nullopt;
300
301 llvm::StringRef Name = [&]() -> llvm::StringRef {
302 for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {
305 return II->getName();
307 return "";
308 }
309 if (const auto *ND = llvm::dyn_cast(D))
310 if (const auto *II = ND->getIdentifier())
311 return II->getName();
312 return "";
313 }();
314 if (Name.empty())
315 return std::nullopt;
316
317 auto It = Symbols->find(Name);
318 if (It == Symbols->end())
319 return std::nullopt;
320 return Symbol(It->second, L);
321}
322
323}
324}
325}
Defines the clang::LangOptions interface.
Provides an interface for querying information about C and C++ Standard Library headers and symbols.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
Decl::Kind getDeclKind() const
Decl - This represents one declaration (or definition), e.g.
DeclContext * getDeclContext()
const LangOptions & getLangOpts() const LLVM_READONLY
Helper to get the language options from the ASTContext.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
bool isEmpty() const
Evaluates true when this declaration name is empty.
static bool classofKind(Kind K)
Represent a C++ namespace.
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
Scope - A scope is a transient data structure that is used while parsing the program.
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
Language
The language for the input, used to select and validate the language standard and possible actions.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)