1bdd1243dSDimitry Andric //===--- StandardLibrary.cpp ------------------------------------*- C++ -*-===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric
9bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/StandardLibrary.h"
10bdd1243dSDimitry Andric #include "clang/AST/Decl.h"
1106c3fb27SDimitry Andric #include "clang/Basic/LangOptions.h"
1206c3fb27SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1306c3fb27SDimitry Andric #include "llvm/ADT/DenseSet.h"
1406c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h"
15bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h"
16bdd1243dSDimitry Andric #include "llvm/Support/Casting.h"
1706c3fb27SDimitry Andric #include <optional>
18bdd1243dSDimitry Andric
19bdd1243dSDimitry Andric namespace clang {
20bdd1243dSDimitry Andric namespace tooling {
21bdd1243dSDimitry Andric namespace stdlib {
22bdd1243dSDimitry Andric
2306c3fb27SDimitry Andric namespace {
2406c3fb27SDimitry Andric // Symbol name -> Symbol::ID, within a namespace.
25bdd1243dSDimitry Andric using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
26bdd1243dSDimitry Andric
2706c3fb27SDimitry Andric // A Mapping per language.
2806c3fb27SDimitry Andric struct SymbolHeaderMapping {
2906c3fb27SDimitry Andric llvm::StringRef *HeaderNames = nullptr;
3006c3fb27SDimitry Andric // Header name => Header::ID
3106c3fb27SDimitry Andric llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;
3206c3fb27SDimitry Andric
3306c3fb27SDimitry Andric unsigned SymbolCount = 0;
3406c3fb27SDimitry Andric // Symbol::ID => symbol qualified_name/name/scope
3506c3fb27SDimitry Andric struct SymbolName {
3606c3fb27SDimitry Andric const char *Data; // std::vector
3706c3fb27SDimitry Andric unsigned ScopeLen; // ~~~~~
3806c3fb27SDimitry Andric unsigned NameLen; // ~~~~~~
scopeclang::tooling::stdlib::__anonec5485b20111::SymbolHeaderMapping::SymbolName3906c3fb27SDimitry Andric StringRef scope() const { return StringRef(Data, ScopeLen); }
nameclang::tooling::stdlib::__anonec5485b20111::SymbolHeaderMapping::SymbolName4006c3fb27SDimitry Andric StringRef name() const { return StringRef(Data + ScopeLen, NameLen); }
qualifiedNameclang::tooling::stdlib::__anonec5485b20111::SymbolHeaderMapping::SymbolName4106c3fb27SDimitry Andric StringRef qualifiedName() const {
4206c3fb27SDimitry Andric return StringRef(Data, ScopeLen + NameLen);
4306c3fb27SDimitry Andric }
4406c3fb27SDimitry Andric } *SymbolNames = nullptr;
4506c3fb27SDimitry Andric // Symbol name -> Symbol::ID, within a namespace.
4606c3fb27SDimitry Andric llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols = nullptr;
4706c3fb27SDimitry Andric // Symbol::ID => Header::ID
4806c3fb27SDimitry Andric llvm::SmallVector<unsigned> *SymbolHeaderIDs = nullptr;
4906c3fb27SDimitry Andric };
5006c3fb27SDimitry Andric } // namespace
5106c3fb27SDimitry Andric static SymbolHeaderMapping
5206c3fb27SDimitry Andric *LanguageMappings[static_cast<unsigned>(Lang::LastValue) + 1];
getMappingPerLang(Lang L)5306c3fb27SDimitry Andric static const SymbolHeaderMapping *getMappingPerLang(Lang L) {
5406c3fb27SDimitry Andric return LanguageMappings[static_cast<unsigned>(L)];
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric
countSymbols(Lang Language)5706c3fb27SDimitry Andric static int countSymbols(Lang Language) {
585f757f3fSDimitry Andric ArrayRef<const char *> Symbols;
595f757f3fSDimitry Andric #define SYMBOL(Name, NS, Header) #NS #Name,
6006c3fb27SDimitry Andric switch (Language) {
615f757f3fSDimitry Andric case Lang::C: {
625f757f3fSDimitry Andric static constexpr const char *CSymbols[] = {
63*0fca6ea1SDimitry Andric #include "CSpecialSymbolMap.inc"
6406c3fb27SDimitry Andric #include "CSymbolMap.inc"
655f757f3fSDimitry Andric };
665f757f3fSDimitry Andric Symbols = CSymbols;
6706c3fb27SDimitry Andric break;
685f757f3fSDimitry Andric }
695f757f3fSDimitry Andric case Lang::CXX: {
705f757f3fSDimitry Andric static constexpr const char *CXXSymbols[] = {
7106c3fb27SDimitry Andric #include "StdSpecialSymbolMap.inc"
7206c3fb27SDimitry Andric #include "StdSymbolMap.inc"
7306c3fb27SDimitry Andric #include "StdTsSymbolMap.inc"
745f757f3fSDimitry Andric };
755f757f3fSDimitry Andric Symbols = CXXSymbols;
7606c3fb27SDimitry Andric break;
7706c3fb27SDimitry Andric }
785f757f3fSDimitry Andric }
79bdd1243dSDimitry Andric #undef SYMBOL
805f757f3fSDimitry Andric return llvm::DenseSet<StringRef>(Symbols.begin(), Symbols.end()).size();
8106c3fb27SDimitry Andric }
82bdd1243dSDimitry Andric
initialize(Lang Language)8306c3fb27SDimitry Andric static int initialize(Lang Language) {
8406c3fb27SDimitry Andric SymbolHeaderMapping *Mapping = new SymbolHeaderMapping();
8506c3fb27SDimitry Andric LanguageMappings[static_cast<unsigned>(Language)] = Mapping;
8606c3fb27SDimitry Andric
8706c3fb27SDimitry Andric unsigned SymCount = countSymbols(Language);
8806c3fb27SDimitry Andric Mapping->SymbolCount = SymCount;
8906c3fb27SDimitry Andric Mapping->SymbolNames =
9006c3fb27SDimitry Andric new std::remove_reference_t<decltype(*Mapping->SymbolNames)>[SymCount];
9106c3fb27SDimitry Andric Mapping->SymbolHeaderIDs = new std::remove_reference_t<
9206c3fb27SDimitry Andric decltype(*Mapping->SymbolHeaderIDs)>[SymCount];
9306c3fb27SDimitry Andric Mapping->NamespaceSymbols =
9406c3fb27SDimitry Andric new std::remove_reference_t<decltype(*Mapping->NamespaceSymbols)>;
9506c3fb27SDimitry Andric Mapping->HeaderIDs =
9606c3fb27SDimitry Andric new std::remove_reference_t<decltype(*Mapping->HeaderIDs)>;
97bdd1243dSDimitry Andric auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {
9806c3fb27SDimitry Andric auto R = Mapping->NamespaceSymbols->try_emplace(NS, nullptr);
99bdd1243dSDimitry Andric if (R.second)
100bdd1243dSDimitry Andric R.first->second = new NSSymbolMap();
101bdd1243dSDimitry Andric return *R.first->second;
102bdd1243dSDimitry Andric };
103bdd1243dSDimitry Andric
104bdd1243dSDimitry Andric auto AddHeader = [&](llvm::StringRef Header) -> unsigned {
10506c3fb27SDimitry Andric return Mapping->HeaderIDs->try_emplace(Header, Mapping->HeaderIDs->size())
10606c3fb27SDimitry Andric .first->second;
107bdd1243dSDimitry Andric };
108bdd1243dSDimitry Andric
10906c3fb27SDimitry Andric auto Add = [&, SymIndex(-1)](llvm::StringRef QName, unsigned NSLen,
110bdd1243dSDimitry Andric llvm::StringRef HeaderName) mutable {
11106c3fb27SDimitry Andric // Correct "Nonefoo" => foo.
11206c3fb27SDimitry Andric // FIXME: get rid of "None" from the generated mapping files.
11306c3fb27SDimitry Andric if (QName.take_front(NSLen) == "None") {
11406c3fb27SDimitry Andric QName = QName.drop_front(NSLen);
11506c3fb27SDimitry Andric NSLen = 0;
11606c3fb27SDimitry Andric }
117bdd1243dSDimitry Andric
11806c3fb27SDimitry Andric if (SymIndex >= 0 &&
11906c3fb27SDimitry Andric Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
12006c3fb27SDimitry Andric // Not a new symbol, use the same index.
12106c3fb27SDimitry Andric assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
12206c3fb27SDimitry Andric [&QName](const SymbolHeaderMapping::SymbolName &S) {
12306c3fb27SDimitry Andric return S.qualifiedName() == QName;
12406c3fb27SDimitry Andric }) &&
12506c3fb27SDimitry Andric "The symbol has been added before, make sure entries in the .inc "
12606c3fb27SDimitry Andric "file are grouped by symbol name!");
12706c3fb27SDimitry Andric } else {
12806c3fb27SDimitry Andric // First symbol or new symbol, increment next available index.
129bdd1243dSDimitry Andric ++SymIndex;
13006c3fb27SDimitry Andric }
13106c3fb27SDimitry Andric Mapping->SymbolNames[SymIndex] = {
13206c3fb27SDimitry Andric QName.data(), NSLen, static_cast<unsigned int>(QName.size() - NSLen)};
13306c3fb27SDimitry Andric if (!HeaderName.empty())
13406c3fb27SDimitry Andric Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));
13506c3fb27SDimitry Andric
13606c3fb27SDimitry Andric NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen));
13706c3fb27SDimitry Andric NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex);
138bdd1243dSDimitry Andric };
1395f757f3fSDimitry Andric
1405f757f3fSDimitry Andric struct Symbol {
1415f757f3fSDimitry Andric const char *QName;
1425f757f3fSDimitry Andric unsigned NSLen;
1435f757f3fSDimitry Andric const char *HeaderName;
1445f757f3fSDimitry Andric };
1455f757f3fSDimitry Andric #define SYMBOL(Name, NS, Header) \
1465f757f3fSDimitry Andric {#NS #Name, static_cast<decltype(Symbol::NSLen)>(StringRef(#NS).size()), \
1475f757f3fSDimitry Andric #Header},
14806c3fb27SDimitry Andric switch (Language) {
1495f757f3fSDimitry Andric case Lang::C: {
1505f757f3fSDimitry Andric static constexpr Symbol CSymbols[] = {
151*0fca6ea1SDimitry Andric #include "CSpecialSymbolMap.inc"
15206c3fb27SDimitry Andric #include "CSymbolMap.inc"
1535f757f3fSDimitry Andric };
1545f757f3fSDimitry Andric for (const Symbol &S : CSymbols)
1555f757f3fSDimitry Andric Add(S.QName, S.NSLen, S.HeaderName);
15606c3fb27SDimitry Andric break;
1575f757f3fSDimitry Andric }
1585f757f3fSDimitry Andric case Lang::CXX: {
1595f757f3fSDimitry Andric static constexpr Symbol CXXSymbols[] = {
16006c3fb27SDimitry Andric #include "StdSpecialSymbolMap.inc"
16106c3fb27SDimitry Andric #include "StdSymbolMap.inc"
16206c3fb27SDimitry Andric #include "StdTsSymbolMap.inc"
1635f757f3fSDimitry Andric };
1645f757f3fSDimitry Andric for (const Symbol &S : CXXSymbols)
1655f757f3fSDimitry Andric Add(S.QName, S.NSLen, S.HeaderName);
16606c3fb27SDimitry Andric break;
16706c3fb27SDimitry Andric }
1685f757f3fSDimitry Andric }
169bdd1243dSDimitry Andric #undef SYMBOL
170bdd1243dSDimitry Andric
17106c3fb27SDimitry Andric Mapping->HeaderNames = new llvm::StringRef[Mapping->HeaderIDs->size()];
17206c3fb27SDimitry Andric for (const auto &E : *Mapping->HeaderIDs)
17306c3fb27SDimitry Andric Mapping->HeaderNames[E.second] = E.first;
174bdd1243dSDimitry Andric
175bdd1243dSDimitry Andric return 0;
176bdd1243dSDimitry Andric }
177bdd1243dSDimitry Andric
ensureInitialized()178bdd1243dSDimitry Andric static void ensureInitialized() {
17906c3fb27SDimitry Andric static int Dummy = []() {
18006c3fb27SDimitry Andric for (unsigned L = 0; L <= static_cast<unsigned>(Lang::LastValue); ++L)
18106c3fb27SDimitry Andric initialize(static_cast<Lang>(L));
18206c3fb27SDimitry Andric return 0;
18306c3fb27SDimitry Andric }();
184bdd1243dSDimitry Andric (void)Dummy;
185bdd1243dSDimitry Andric }
186bdd1243dSDimitry Andric
all(Lang L)18706c3fb27SDimitry Andric std::vector<Header> Header::all(Lang L) {
188bdd1243dSDimitry Andric ensureInitialized();
18906c3fb27SDimitry Andric std::vector<Header> Result;
19006c3fb27SDimitry Andric const auto *Mapping = getMappingPerLang(L);
19106c3fb27SDimitry Andric Result.reserve(Mapping->HeaderIDs->size());
19206c3fb27SDimitry Andric for (unsigned I = 0, E = Mapping->HeaderIDs->size(); I < E; ++I)
19306c3fb27SDimitry Andric Result.push_back(Header(I, L));
19406c3fb27SDimitry Andric return Result;
195bdd1243dSDimitry Andric }
named(llvm::StringRef Name,Lang L)19606c3fb27SDimitry Andric std::optional<Header> Header::named(llvm::StringRef Name, Lang L) {
197bdd1243dSDimitry Andric ensureInitialized();
19806c3fb27SDimitry Andric const auto *Mapping = getMappingPerLang(L);
19906c3fb27SDimitry Andric auto It = Mapping->HeaderIDs->find(Name);
20006c3fb27SDimitry Andric if (It == Mapping->HeaderIDs->end())
20106c3fb27SDimitry Andric return std::nullopt;
20206c3fb27SDimitry Andric return Header(It->second, L);
20306c3fb27SDimitry Andric }
name() const20406c3fb27SDimitry Andric llvm::StringRef Header::name() const {
20506c3fb27SDimitry Andric return getMappingPerLang(Language)->HeaderNames[ID];
20606c3fb27SDimitry Andric }
20706c3fb27SDimitry Andric
all(Lang L)20806c3fb27SDimitry Andric std::vector<Symbol> Symbol::all(Lang L) {
20906c3fb27SDimitry Andric ensureInitialized();
21006c3fb27SDimitry Andric std::vector<Symbol> Result;
21106c3fb27SDimitry Andric const auto *Mapping = getMappingPerLang(L);
21206c3fb27SDimitry Andric Result.reserve(Mapping->SymbolCount);
21306c3fb27SDimitry Andric for (unsigned I = 0, E = Mapping->SymbolCount; I < E; ++I)
21406c3fb27SDimitry Andric Result.push_back(Symbol(I, L));
21506c3fb27SDimitry Andric return Result;
21606c3fb27SDimitry Andric }
scope() const21706c3fb27SDimitry Andric llvm::StringRef Symbol::scope() const {
21806c3fb27SDimitry Andric return getMappingPerLang(Language)->SymbolNames[ID].scope();
21906c3fb27SDimitry Andric }
name() const22006c3fb27SDimitry Andric llvm::StringRef Symbol::name() const {
22106c3fb27SDimitry Andric return getMappingPerLang(Language)->SymbolNames[ID].name();
22206c3fb27SDimitry Andric }
qualifiedName() const22306c3fb27SDimitry Andric llvm::StringRef Symbol::qualifiedName() const {
22406c3fb27SDimitry Andric return getMappingPerLang(Language)->SymbolNames[ID].qualifiedName();
22506c3fb27SDimitry Andric }
named(llvm::StringRef Scope,llvm::StringRef Name,Lang L)22606c3fb27SDimitry Andric std::optional<Symbol> Symbol::named(llvm::StringRef Scope, llvm::StringRef Name,
22706c3fb27SDimitry Andric Lang L) {
22806c3fb27SDimitry Andric ensureInitialized();
22906c3fb27SDimitry Andric
23006c3fb27SDimitry Andric if (NSSymbolMap *NSSymbols =
23106c3fb27SDimitry Andric getMappingPerLang(L)->NamespaceSymbols->lookup(Scope)) {
232bdd1243dSDimitry Andric auto It = NSSymbols->find(Name);
233bdd1243dSDimitry Andric if (It != NSSymbols->end())
23406c3fb27SDimitry Andric return Symbol(It->second, L);
235bdd1243dSDimitry Andric }
236bdd1243dSDimitry Andric return std::nullopt;
237bdd1243dSDimitry Andric }
header() const23806c3fb27SDimitry Andric std::optional<Header> Symbol::header() const {
23906c3fb27SDimitry Andric const auto& Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];
24006c3fb27SDimitry Andric if (Headers.empty())
24106c3fb27SDimitry Andric return std::nullopt;
24206c3fb27SDimitry Andric return Header(Headers.front(), Language);
24306c3fb27SDimitry Andric }
headers() const244bdd1243dSDimitry Andric llvm::SmallVector<Header> Symbol::headers() const {
24506c3fb27SDimitry Andric llvm::SmallVector<Header> Results;
24606c3fb27SDimitry Andric for (auto HeaderID : getMappingPerLang(Language)->SymbolHeaderIDs[ID])
24706c3fb27SDimitry Andric Results.emplace_back(Header(HeaderID, Language));
24806c3fb27SDimitry Andric return Results;
249bdd1243dSDimitry Andric }
250bdd1243dSDimitry Andric
Recognizer()251bdd1243dSDimitry Andric Recognizer::Recognizer() { ensureInitialized(); }
252bdd1243dSDimitry Andric
namespaceSymbols(const DeclContext * DC,Lang L)25306c3fb27SDimitry Andric NSSymbolMap *Recognizer::namespaceSymbols(const DeclContext *DC, Lang L) {
25406c3fb27SDimitry Andric if (DC->isTranslationUnit()) // global scope.
25506c3fb27SDimitry Andric return getMappingPerLang(L)->NamespaceSymbols->lookup("");
25606c3fb27SDimitry Andric
25706c3fb27SDimitry Andric auto It = NamespaceCache.find(DC);
258bdd1243dSDimitry Andric if (It != NamespaceCache.end())
259bdd1243dSDimitry Andric return It->second;
26006c3fb27SDimitry Andric const NamespaceDecl *D = llvm::cast<NamespaceDecl>(DC);
261bdd1243dSDimitry Andric NSSymbolMap *Result = [&]() -> NSSymbolMap * {
26206c3fb27SDimitry Andric if (D->isAnonymousNamespace())
263bdd1243dSDimitry Andric return nullptr;
264bdd1243dSDimitry Andric // Print the namespace and its parents ommitting inline scopes.
265bdd1243dSDimitry Andric std::string Scope;
266bdd1243dSDimitry Andric for (const auto *ND = D; ND;
267bdd1243dSDimitry Andric ND = llvm::dyn_cast_or_null<NamespaceDecl>(ND->getParent()))
268bdd1243dSDimitry Andric if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace())
269bdd1243dSDimitry Andric Scope = ND->getName().str() + "::" + Scope;
27006c3fb27SDimitry Andric return getMappingPerLang(L)->NamespaceSymbols->lookup(Scope);
271bdd1243dSDimitry Andric }();
272bdd1243dSDimitry Andric NamespaceCache.try_emplace(D, Result);
273bdd1243dSDimitry Andric return Result;
274bdd1243dSDimitry Andric }
275bdd1243dSDimitry Andric
operator ()(const Decl * D)276bdd1243dSDimitry Andric std::optional<Symbol> Recognizer::operator()(const Decl *D) {
27706c3fb27SDimitry Andric Lang L;
2785f757f3fSDimitry Andric if (D->getLangOpts().CPlusPlus)
27906c3fb27SDimitry Andric L = Lang::CXX;
2805f757f3fSDimitry Andric else if (D->getLangOpts().C99)
28106c3fb27SDimitry Andric L = Lang::C;
2825f757f3fSDimitry Andric else
28306c3fb27SDimitry Andric return std::nullopt; // not a supported language.
28406c3fb27SDimitry Andric
285bdd1243dSDimitry Andric // If D is std::vector::iterator, `vector` is the outer symbol to look up.
286bdd1243dSDimitry Andric // We keep all the candidate DCs as some may turn out to be anon enums.
287bdd1243dSDimitry Andric // Do this resolution lazily as we may turn out not to have a std namespace.
288bdd1243dSDimitry Andric llvm::SmallVector<const DeclContext *> IntermediateDecl;
289bdd1243dSDimitry Andric const DeclContext *DC = D->getDeclContext();
29006c3fb27SDimitry Andric if (!DC) // The passed D is a TranslationUnitDecl!
29106c3fb27SDimitry Andric return std::nullopt;
29206c3fb27SDimitry Andric while (!DC->isNamespace() && !DC->isTranslationUnit()) {
293bdd1243dSDimitry Andric if (NamedDecl::classofKind(DC->getDeclKind()))
294bdd1243dSDimitry Andric IntermediateDecl.push_back(DC);
295bdd1243dSDimitry Andric DC = DC->getParent();
296bdd1243dSDimitry Andric }
29706c3fb27SDimitry Andric NSSymbolMap *Symbols = namespaceSymbols(DC, L);
298bdd1243dSDimitry Andric if (!Symbols)
299bdd1243dSDimitry Andric return std::nullopt;
300bdd1243dSDimitry Andric
301bdd1243dSDimitry Andric llvm::StringRef Name = [&]() -> llvm::StringRef {
302bdd1243dSDimitry Andric for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {
303bdd1243dSDimitry Andric DeclarationName N = cast<NamedDecl>(SymDC)->getDeclName();
304bdd1243dSDimitry Andric if (const auto *II = N.getAsIdentifierInfo())
305bdd1243dSDimitry Andric return II->getName();
306bdd1243dSDimitry Andric if (!N.isEmpty())
307bdd1243dSDimitry Andric return ""; // e.g. operator<: give up
308bdd1243dSDimitry Andric }
309bdd1243dSDimitry Andric if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
310bdd1243dSDimitry Andric if (const auto *II = ND->getIdentifier())
311bdd1243dSDimitry Andric return II->getName();
312bdd1243dSDimitry Andric return "";
313bdd1243dSDimitry Andric }();
314bdd1243dSDimitry Andric if (Name.empty())
315bdd1243dSDimitry Andric return std::nullopt;
316bdd1243dSDimitry Andric
317bdd1243dSDimitry Andric auto It = Symbols->find(Name);
318bdd1243dSDimitry Andric if (It == Symbols->end())
319bdd1243dSDimitry Andric return std::nullopt;
32006c3fb27SDimitry Andric return Symbol(It->second, L);
321bdd1243dSDimitry Andric }
322bdd1243dSDimitry Andric
323bdd1243dSDimitry Andric } // namespace stdlib
324bdd1243dSDimitry Andric } // namespace tooling
325bdd1243dSDimitry Andric } // namespace clang
326