1*bdd1243dSDimitry Andric //===--- StandardLibrary.cpp ------------------------------------*- C++ -*-===// 2*bdd1243dSDimitry Andric // 3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bdd1243dSDimitry Andric // 7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8*bdd1243dSDimitry Andric 9*bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/StandardLibrary.h" 10*bdd1243dSDimitry Andric #include "clang/AST/Decl.h" 11*bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 12*bdd1243dSDimitry Andric #include "llvm/Support/Casting.h" 13*bdd1243dSDimitry Andric 14*bdd1243dSDimitry Andric namespace clang { 15*bdd1243dSDimitry Andric namespace tooling { 16*bdd1243dSDimitry Andric namespace stdlib { 17*bdd1243dSDimitry Andric 18*bdd1243dSDimitry Andric static llvm::StringRef *HeaderNames; 19*bdd1243dSDimitry Andric static std::pair<llvm::StringRef, llvm::StringRef> *SymbolNames; 20*bdd1243dSDimitry Andric static unsigned *SymbolHeaderIDs; 21*bdd1243dSDimitry Andric static llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs; 22*bdd1243dSDimitry Andric // Maps symbol name -> Symbol::ID, within a namespace. 23*bdd1243dSDimitry Andric using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>; 24*bdd1243dSDimitry Andric static llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols; 25*bdd1243dSDimitry Andric 26*bdd1243dSDimitry Andric static int initialize() { 27*bdd1243dSDimitry Andric unsigned SymCount = 0; 28*bdd1243dSDimitry Andric #define SYMBOL(Name, NS, Header) ++SymCount; 29*bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/CSymbolMap.inc" 30*bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/StdSymbolMap.inc" 31*bdd1243dSDimitry Andric #undef SYMBOL 32*bdd1243dSDimitry Andric SymbolNames = new std::remove_reference_t<decltype(*SymbolNames)>[SymCount]; 33*bdd1243dSDimitry Andric SymbolHeaderIDs = 34*bdd1243dSDimitry Andric new std::remove_reference_t<decltype(*SymbolHeaderIDs)>[SymCount]; 35*bdd1243dSDimitry Andric NamespaceSymbols = new std::remove_reference_t<decltype(*NamespaceSymbols)>; 36*bdd1243dSDimitry Andric HeaderIDs = new std::remove_reference_t<decltype(*HeaderIDs)>; 37*bdd1243dSDimitry Andric 38*bdd1243dSDimitry Andric auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & { 39*bdd1243dSDimitry Andric auto R = NamespaceSymbols->try_emplace(NS, nullptr); 40*bdd1243dSDimitry Andric if (R.second) 41*bdd1243dSDimitry Andric R.first->second = new NSSymbolMap(); 42*bdd1243dSDimitry Andric return *R.first->second; 43*bdd1243dSDimitry Andric }; 44*bdd1243dSDimitry Andric 45*bdd1243dSDimitry Andric auto AddHeader = [&](llvm::StringRef Header) -> unsigned { 46*bdd1243dSDimitry Andric return HeaderIDs->try_emplace(Header, HeaderIDs->size()).first->second; 47*bdd1243dSDimitry Andric }; 48*bdd1243dSDimitry Andric 49*bdd1243dSDimitry Andric auto Add = [&, SymIndex(0)](llvm::StringRef Name, llvm::StringRef NS, 50*bdd1243dSDimitry Andric llvm::StringRef HeaderName) mutable { 51*bdd1243dSDimitry Andric if (NS == "None") 52*bdd1243dSDimitry Andric NS = ""; 53*bdd1243dSDimitry Andric 54*bdd1243dSDimitry Andric SymbolNames[SymIndex] = {NS, Name}; 55*bdd1243dSDimitry Andric SymbolHeaderIDs[SymIndex] = AddHeader(HeaderName); 56*bdd1243dSDimitry Andric 57*bdd1243dSDimitry Andric NSSymbolMap &NSSymbols = AddNS(NS); 58*bdd1243dSDimitry Andric NSSymbols.try_emplace(Name, SymIndex); 59*bdd1243dSDimitry Andric 60*bdd1243dSDimitry Andric ++SymIndex; 61*bdd1243dSDimitry Andric }; 62*bdd1243dSDimitry Andric #define SYMBOL(Name, NS, Header) Add(#Name, #NS, #Header); 63*bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/CSymbolMap.inc" 64*bdd1243dSDimitry Andric #include "clang/Tooling/Inclusions/StdSymbolMap.inc" 65*bdd1243dSDimitry Andric #undef SYMBOL 66*bdd1243dSDimitry Andric 67*bdd1243dSDimitry Andric HeaderNames = new llvm::StringRef[HeaderIDs->size()]; 68*bdd1243dSDimitry Andric for (const auto &E : *HeaderIDs) 69*bdd1243dSDimitry Andric HeaderNames[E.second] = E.first; 70*bdd1243dSDimitry Andric 71*bdd1243dSDimitry Andric return 0; 72*bdd1243dSDimitry Andric } 73*bdd1243dSDimitry Andric 74*bdd1243dSDimitry Andric static void ensureInitialized() { 75*bdd1243dSDimitry Andric static int Dummy = initialize(); 76*bdd1243dSDimitry Andric (void)Dummy; 77*bdd1243dSDimitry Andric } 78*bdd1243dSDimitry Andric 79*bdd1243dSDimitry Andric std::optional<Header> Header::named(llvm::StringRef Name) { 80*bdd1243dSDimitry Andric ensureInitialized(); 81*bdd1243dSDimitry Andric auto It = HeaderIDs->find(Name); 82*bdd1243dSDimitry Andric if (It == HeaderIDs->end()) 83*bdd1243dSDimitry Andric return std::nullopt; 84*bdd1243dSDimitry Andric return Header(It->second); 85*bdd1243dSDimitry Andric } 86*bdd1243dSDimitry Andric llvm::StringRef Header::name() const { return HeaderNames[ID]; } 87*bdd1243dSDimitry Andric llvm::StringRef Symbol::scope() const { return SymbolNames[ID].first; } 88*bdd1243dSDimitry Andric llvm::StringRef Symbol::name() const { return SymbolNames[ID].second; } 89*bdd1243dSDimitry Andric std::optional<Symbol> Symbol::named(llvm::StringRef Scope, 90*bdd1243dSDimitry Andric llvm::StringRef Name) { 91*bdd1243dSDimitry Andric ensureInitialized(); 92*bdd1243dSDimitry Andric if (NSSymbolMap *NSSymbols = NamespaceSymbols->lookup(Scope)) { 93*bdd1243dSDimitry Andric auto It = NSSymbols->find(Name); 94*bdd1243dSDimitry Andric if (It != NSSymbols->end()) 95*bdd1243dSDimitry Andric return Symbol(It->second); 96*bdd1243dSDimitry Andric } 97*bdd1243dSDimitry Andric return std::nullopt; 98*bdd1243dSDimitry Andric } 99*bdd1243dSDimitry Andric Header Symbol::header() const { return Header(SymbolHeaderIDs[ID]); } 100*bdd1243dSDimitry Andric llvm::SmallVector<Header> Symbol::headers() const { 101*bdd1243dSDimitry Andric return {header()}; // FIXME: multiple in case of ambiguity 102*bdd1243dSDimitry Andric } 103*bdd1243dSDimitry Andric 104*bdd1243dSDimitry Andric Recognizer::Recognizer() { ensureInitialized(); } 105*bdd1243dSDimitry Andric 106*bdd1243dSDimitry Andric NSSymbolMap *Recognizer::namespaceSymbols(const NamespaceDecl *D) { 107*bdd1243dSDimitry Andric auto It = NamespaceCache.find(D); 108*bdd1243dSDimitry Andric if (It != NamespaceCache.end()) 109*bdd1243dSDimitry Andric return It->second; 110*bdd1243dSDimitry Andric 111*bdd1243dSDimitry Andric NSSymbolMap *Result = [&]() -> NSSymbolMap * { 112*bdd1243dSDimitry Andric if (D && D->isAnonymousNamespace()) 113*bdd1243dSDimitry Andric return nullptr; 114*bdd1243dSDimitry Andric // Print the namespace and its parents ommitting inline scopes. 115*bdd1243dSDimitry Andric std::string Scope; 116*bdd1243dSDimitry Andric for (const auto *ND = D; ND; 117*bdd1243dSDimitry Andric ND = llvm::dyn_cast_or_null<NamespaceDecl>(ND->getParent())) 118*bdd1243dSDimitry Andric if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace()) 119*bdd1243dSDimitry Andric Scope = ND->getName().str() + "::" + Scope; 120*bdd1243dSDimitry Andric return NamespaceSymbols->lookup(Scope); 121*bdd1243dSDimitry Andric }(); 122*bdd1243dSDimitry Andric NamespaceCache.try_emplace(D, Result); 123*bdd1243dSDimitry Andric return Result; 124*bdd1243dSDimitry Andric } 125*bdd1243dSDimitry Andric 126*bdd1243dSDimitry Andric std::optional<Symbol> Recognizer::operator()(const Decl *D) { 127*bdd1243dSDimitry Andric // If D is std::vector::iterator, `vector` is the outer symbol to look up. 128*bdd1243dSDimitry Andric // We keep all the candidate DCs as some may turn out to be anon enums. 129*bdd1243dSDimitry Andric // Do this resolution lazily as we may turn out not to have a std namespace. 130*bdd1243dSDimitry Andric llvm::SmallVector<const DeclContext *> IntermediateDecl; 131*bdd1243dSDimitry Andric const DeclContext *DC = D->getDeclContext(); 132*bdd1243dSDimitry Andric while (DC && !DC->isNamespace()) { 133*bdd1243dSDimitry Andric if (NamedDecl::classofKind(DC->getDeclKind())) 134*bdd1243dSDimitry Andric IntermediateDecl.push_back(DC); 135*bdd1243dSDimitry Andric DC = DC->getParent(); 136*bdd1243dSDimitry Andric } 137*bdd1243dSDimitry Andric NSSymbolMap *Symbols = namespaceSymbols(cast_or_null<NamespaceDecl>(DC)); 138*bdd1243dSDimitry Andric if (!Symbols) 139*bdd1243dSDimitry Andric return std::nullopt; 140*bdd1243dSDimitry Andric 141*bdd1243dSDimitry Andric llvm::StringRef Name = [&]() -> llvm::StringRef { 142*bdd1243dSDimitry Andric for (const auto *SymDC : llvm::reverse(IntermediateDecl)) { 143*bdd1243dSDimitry Andric DeclarationName N = cast<NamedDecl>(SymDC)->getDeclName(); 144*bdd1243dSDimitry Andric if (const auto *II = N.getAsIdentifierInfo()) 145*bdd1243dSDimitry Andric return II->getName(); 146*bdd1243dSDimitry Andric if (!N.isEmpty()) 147*bdd1243dSDimitry Andric return ""; // e.g. operator<: give up 148*bdd1243dSDimitry Andric } 149*bdd1243dSDimitry Andric if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) 150*bdd1243dSDimitry Andric if (const auto *II = ND->getIdentifier()) 151*bdd1243dSDimitry Andric return II->getName(); 152*bdd1243dSDimitry Andric return ""; 153*bdd1243dSDimitry Andric }(); 154*bdd1243dSDimitry Andric if (Name.empty()) 155*bdd1243dSDimitry Andric return std::nullopt; 156*bdd1243dSDimitry Andric 157*bdd1243dSDimitry Andric auto It = Symbols->find(Name); 158*bdd1243dSDimitry Andric if (It == Symbols->end()) 159*bdd1243dSDimitry Andric return std::nullopt; 160*bdd1243dSDimitry Andric return Symbol(It->second); 161*bdd1243dSDimitry Andric } 162*bdd1243dSDimitry Andric 163*bdd1243dSDimitry Andric } // namespace stdlib 164*bdd1243dSDimitry Andric } // namespace tooling 165*bdd1243dSDimitry Andric } // namespace clang 166