xref: /freebsd-src/contrib/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;  //      ~~~~~~
3906c3fb27SDimitry Andric     StringRef scope() const { return StringRef(Data, ScopeLen); }
4006c3fb27SDimitry Andric     StringRef name() const { return StringRef(Data + ScopeLen, NameLen); }
4106c3fb27SDimitry 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];
5306c3fb27SDimitry Andric static const SymbolHeaderMapping *getMappingPerLang(Lang L) {
5406c3fb27SDimitry Andric   return LanguageMappings[static_cast<unsigned>(L)];
5506c3fb27SDimitry Andric }
5606c3fb27SDimitry Andric 
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 
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 
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 
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 }
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 }
20406c3fb27SDimitry Andric llvm::StringRef Header::name() const {
20506c3fb27SDimitry Andric   return getMappingPerLang(Language)->HeaderNames[ID];
20606c3fb27SDimitry Andric }
20706c3fb27SDimitry Andric 
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 }
21706c3fb27SDimitry Andric llvm::StringRef Symbol::scope() const {
21806c3fb27SDimitry Andric   return getMappingPerLang(Language)->SymbolNames[ID].scope();
21906c3fb27SDimitry Andric }
22006c3fb27SDimitry Andric llvm::StringRef Symbol::name() const {
22106c3fb27SDimitry Andric   return getMappingPerLang(Language)->SymbolNames[ID].name();
22206c3fb27SDimitry Andric }
22306c3fb27SDimitry Andric llvm::StringRef Symbol::qualifiedName() const {
22406c3fb27SDimitry Andric   return getMappingPerLang(Language)->SymbolNames[ID].qualifiedName();
22506c3fb27SDimitry Andric }
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 }
23806c3fb27SDimitry 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 }
244bdd1243dSDimitry 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 
251bdd1243dSDimitry Andric Recognizer::Recognizer() { ensureInitialized(); }
252bdd1243dSDimitry Andric 
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 
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