xref: /llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp (revision c0ce44e8fc03882641f270539265b20dba0fffdd)
1d1f13c54SKadir Cetinkaya //===--- StandardLibrary.cpp ------------------------------------*- C++ -*-===//
2d1f13c54SKadir Cetinkaya //
3d1f13c54SKadir Cetinkaya // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d1f13c54SKadir Cetinkaya // See https://llvm.org/LICENSE.txt for license information.
5d1f13c54SKadir Cetinkaya // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d1f13c54SKadir Cetinkaya //
7d1f13c54SKadir Cetinkaya //===----------------------------------------------------------------------===//
8d1f13c54SKadir Cetinkaya 
9d1f13c54SKadir Cetinkaya #include "clang/Tooling/Inclusions/StandardLibrary.h"
10d03ee70dSSam McCall #include "clang/AST/Decl.h"
111285172cSViktoriia Bakalova #include "clang/Basic/LangOptions.h"
121ab62d9dSHaojian Wu #include "llvm/ADT/ArrayRef.h"
131ab62d9dSHaojian Wu #include "llvm/ADT/DenseSet.h"
141ab62d9dSHaojian Wu #include "llvm/ADT/STLExtras.h"
15d1f13c54SKadir Cetinkaya #include "llvm/ADT/StringRef.h"
16d1f13c54SKadir Cetinkaya #include "llvm/Support/Casting.h"
175a623c2aSKadir Cetinkaya #include <optional>
18d1f13c54SKadir Cetinkaya 
19d1f13c54SKadir Cetinkaya namespace clang {
20d1f13c54SKadir Cetinkaya namespace tooling {
21d1f13c54SKadir Cetinkaya namespace stdlib {
22d1f13c54SKadir Cetinkaya 
231285172cSViktoriia Bakalova namespace {
241285172cSViktoriia Bakalova // Symbol name -> Symbol::ID, within a namespace.
251285172cSViktoriia Bakalova using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
26e1aaa314SSam McCall 
271285172cSViktoriia Bakalova // A Mapping per language.
281285172cSViktoriia Bakalova struct SymbolHeaderMapping {
291285172cSViktoriia Bakalova   llvm::StringRef *HeaderNames = nullptr;
301285172cSViktoriia Bakalova   // Header name => Header::ID
311285172cSViktoriia Bakalova   llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;
321285172cSViktoriia Bakalova 
331285172cSViktoriia Bakalova   unsigned SymbolCount = 0;
34e1aaa314SSam McCall   // Symbol::ID => symbol qualified_name/name/scope
351285172cSViktoriia Bakalova   struct SymbolName {
36e1aaa314SSam McCall     const char *Data;  // std::vector
37e1aaa314SSam McCall     unsigned ScopeLen; // ~~~~~
38e1aaa314SSam McCall     unsigned NameLen;  //      ~~~~~~
39d46d44e3SHaojian Wu     StringRef scope() const { return StringRef(Data, ScopeLen); }
40d46d44e3SHaojian Wu     StringRef name() const { return StringRef(Data + ScopeLen, NameLen); }
41d46d44e3SHaojian Wu     StringRef qualifiedName() const {
42d46d44e3SHaojian Wu       return StringRef(Data, ScopeLen + NameLen);
43d46d44e3SHaojian Wu     }
441285172cSViktoriia Bakalova   } *SymbolNames = nullptr;
45e1aaa314SSam McCall   // Symbol name -> Symbol::ID, within a namespace.
461285172cSViktoriia Bakalova   llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols = nullptr;
47e1aaa314SSam McCall   // Symbol::ID => Header::ID
481ab62d9dSHaojian Wu   llvm::SmallVector<unsigned> *SymbolHeaderIDs = nullptr;
491285172cSViktoriia Bakalova };
501285172cSViktoriia Bakalova } // namespace
511285172cSViktoriia Bakalova static SymbolHeaderMapping
521285172cSViktoriia Bakalova     *LanguageMappings[static_cast<unsigned>(Lang::LastValue) + 1];
531285172cSViktoriia Bakalova static const SymbolHeaderMapping *getMappingPerLang(Lang L) {
541285172cSViktoriia Bakalova   return LanguageMappings[static_cast<unsigned>(L)];
551285172cSViktoriia Bakalova }
56d1f13c54SKadir Cetinkaya 
571285172cSViktoriia Bakalova static int countSymbols(Lang Language) {
584674e303SBenjamin Kramer   ArrayRef<const char *> Symbols;
594674e303SBenjamin Kramer #define SYMBOL(Name, NS, Header) #NS #Name,
601285172cSViktoriia Bakalova   switch (Language) {
6124f068b0SBenjamin Kramer   case Lang::C: {
624674e303SBenjamin Kramer     static constexpr const char *CSymbols[] = {
63756c2056Skadir çetinkaya #include "CSpecialSymbolMap.inc"
64c751264aSHaojian Wu #include "CSymbolMap.inc"
654674e303SBenjamin Kramer     };
664674e303SBenjamin Kramer     Symbols = CSymbols;
671285172cSViktoriia Bakalova     break;
6824f068b0SBenjamin Kramer   }
6924f068b0SBenjamin Kramer   case Lang::CXX: {
704674e303SBenjamin Kramer     static constexpr const char *CXXSymbols[] = {
7111dcd885SHaojian Wu #include "StdSpecialSymbolMap.inc"
72d4021ed3SYounan Zhang #include "StdSymbolMap.inc"
73d4021ed3SYounan Zhang #include "StdTsSymbolMap.inc"
744674e303SBenjamin Kramer     };
754674e303SBenjamin Kramer     Symbols = CXXSymbols;
761285172cSViktoriia Bakalova     break;
771285172cSViktoriia Bakalova   }
7824f068b0SBenjamin Kramer   }
79d1f13c54SKadir Cetinkaya #undef SYMBOL
804674e303SBenjamin Kramer   return llvm::DenseSet<StringRef>(Symbols.begin(), Symbols.end()).size();
811285172cSViktoriia Bakalova }
82d1f13c54SKadir Cetinkaya 
831285172cSViktoriia Bakalova static int initialize(Lang Language) {
841285172cSViktoriia Bakalova   SymbolHeaderMapping *Mapping = new SymbolHeaderMapping();
851285172cSViktoriia Bakalova   LanguageMappings[static_cast<unsigned>(Language)] = Mapping;
861285172cSViktoriia Bakalova 
871285172cSViktoriia Bakalova   unsigned SymCount = countSymbols(Language);
881285172cSViktoriia Bakalova   Mapping->SymbolCount = SymCount;
891285172cSViktoriia Bakalova   Mapping->SymbolNames =
901285172cSViktoriia Bakalova       new std::remove_reference_t<decltype(*Mapping->SymbolNames)>[SymCount];
911285172cSViktoriia Bakalova   Mapping->SymbolHeaderIDs = new std::remove_reference_t<
921285172cSViktoriia Bakalova       decltype(*Mapping->SymbolHeaderIDs)>[SymCount];
931285172cSViktoriia Bakalova   Mapping->NamespaceSymbols =
941285172cSViktoriia Bakalova       new std::remove_reference_t<decltype(*Mapping->NamespaceSymbols)>;
951285172cSViktoriia Bakalova   Mapping->HeaderIDs =
961285172cSViktoriia Bakalova       new std::remove_reference_t<decltype(*Mapping->HeaderIDs)>;
97d1f13c54SKadir Cetinkaya   auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {
981285172cSViktoriia Bakalova     auto R = Mapping->NamespaceSymbols->try_emplace(NS, nullptr);
99d1f13c54SKadir Cetinkaya     if (R.second)
100d1f13c54SKadir Cetinkaya       R.first->second = new NSSymbolMap();
101d1f13c54SKadir Cetinkaya     return *R.first->second;
102d1f13c54SKadir Cetinkaya   };
103d1f13c54SKadir Cetinkaya 
104d1f13c54SKadir Cetinkaya   auto AddHeader = [&](llvm::StringRef Header) -> unsigned {
1051285172cSViktoriia Bakalova     return Mapping->HeaderIDs->try_emplace(Header, Mapping->HeaderIDs->size())
1061285172cSViktoriia Bakalova         .first->second;
107d1f13c54SKadir Cetinkaya   };
108d1f13c54SKadir Cetinkaya 
1091ab62d9dSHaojian Wu   auto Add = [&, SymIndex(-1)](llvm::StringRef QName, unsigned NSLen,
110d1f13c54SKadir Cetinkaya                                llvm::StringRef HeaderName) mutable {
111e1aaa314SSam McCall     // Correct "Nonefoo" => foo.
112e1aaa314SSam McCall     // FIXME: get rid of "None" from the generated mapping files.
113e1aaa314SSam McCall     if (QName.take_front(NSLen) == "None") {
114e1aaa314SSam McCall       QName = QName.drop_front(NSLen);
115e1aaa314SSam McCall       NSLen = 0;
116e1aaa314SSam McCall     }
117d1f13c54SKadir Cetinkaya 
118*c0ce44e8SVadim D.     if (SymIndex > 0) {
1191ab62d9dSHaojian Wu       assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
1201ab62d9dSHaojian Wu                            [&QName](const SymbolHeaderMapping::SymbolName &S) {
1211ab62d9dSHaojian Wu                              return S.qualifiedName() == QName;
1221ab62d9dSHaojian Wu                            }) &&
1231ab62d9dSHaojian Wu              "The symbol has been added before, make sure entries in the .inc "
1241ab62d9dSHaojian Wu              "file are grouped by symbol name!");
125*c0ce44e8SVadim D.     }
126*c0ce44e8SVadim D.     if (SymIndex < 0 ||
127*c0ce44e8SVadim D.         Mapping->SymbolNames[SymIndex].qualifiedName() != QName) {
1281ab62d9dSHaojian Wu       // First symbol or new symbol, increment next available index.
1291ab62d9dSHaojian Wu       ++SymIndex;
130*c0ce44e8SVadim D.     } // Else use the same index.
1311285172cSViktoriia Bakalova     Mapping->SymbolNames[SymIndex] = {
1321285172cSViktoriia Bakalova         QName.data(), NSLen, static_cast<unsigned int>(QName.size() - NSLen)};
1335a623c2aSKadir Cetinkaya     if (!HeaderName.empty())
1341ab62d9dSHaojian Wu        Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));
135d1f13c54SKadir Cetinkaya 
136e1aaa314SSam McCall     NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen));
137e1aaa314SSam McCall     NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex);
138d1f13c54SKadir Cetinkaya   };
1394674e303SBenjamin Kramer 
1404674e303SBenjamin Kramer   struct Symbol {
1414674e303SBenjamin Kramer     const char *QName;
1424674e303SBenjamin Kramer     unsigned NSLen;
1434674e303SBenjamin Kramer     const char *HeaderName;
1444674e303SBenjamin Kramer   };
145764c3afdSKrzysztof Parzyszek #define SYMBOL(Name, NS, Header)                                               \
146764c3afdSKrzysztof Parzyszek   {#NS #Name, static_cast<decltype(Symbol::NSLen)>(StringRef(#NS).size()),     \
147764c3afdSKrzysztof Parzyszek    #Header},
1481285172cSViktoriia Bakalova   switch (Language) {
14924f068b0SBenjamin Kramer   case Lang::C: {
1504674e303SBenjamin Kramer     static constexpr Symbol CSymbols[] = {
151756c2056Skadir çetinkaya #include "CSpecialSymbolMap.inc"
152c751264aSHaojian Wu #include "CSymbolMap.inc"
1534674e303SBenjamin Kramer     };
1544674e303SBenjamin Kramer     for (const Symbol &S : CSymbols)
1554674e303SBenjamin Kramer       Add(S.QName, S.NSLen, S.HeaderName);
1561285172cSViktoriia Bakalova     break;
15724f068b0SBenjamin Kramer   }
15824f068b0SBenjamin Kramer   case Lang::CXX: {
1594674e303SBenjamin Kramer     static constexpr Symbol CXXSymbols[] = {
16011dcd885SHaojian Wu #include "StdSpecialSymbolMap.inc"
161d4021ed3SYounan Zhang #include "StdSymbolMap.inc"
162d4021ed3SYounan Zhang #include "StdTsSymbolMap.inc"
1634674e303SBenjamin Kramer     };
1644674e303SBenjamin Kramer     for (const Symbol &S : CXXSymbols)
1654674e303SBenjamin Kramer       Add(S.QName, S.NSLen, S.HeaderName);
1661285172cSViktoriia Bakalova     break;
1671285172cSViktoriia Bakalova   }
16824f068b0SBenjamin Kramer   }
169d1f13c54SKadir Cetinkaya #undef SYMBOL
170d1f13c54SKadir Cetinkaya 
1711285172cSViktoriia Bakalova   Mapping->HeaderNames = new llvm::StringRef[Mapping->HeaderIDs->size()];
1721285172cSViktoriia Bakalova   for (const auto &E : *Mapping->HeaderIDs)
1731285172cSViktoriia Bakalova     Mapping->HeaderNames[E.second] = E.first;
174d1f13c54SKadir Cetinkaya 
175d1f13c54SKadir Cetinkaya   return 0;
176d1f13c54SKadir Cetinkaya }
177d1f13c54SKadir Cetinkaya 
178d1f13c54SKadir Cetinkaya static void ensureInitialized() {
1791285172cSViktoriia Bakalova   static int Dummy = []() {
1801285172cSViktoriia Bakalova     for (unsigned L = 0; L <= static_cast<unsigned>(Lang::LastValue); ++L)
1811285172cSViktoriia Bakalova       initialize(static_cast<Lang>(L));
1821285172cSViktoriia Bakalova     return 0;
1831285172cSViktoriia Bakalova   }();
184d1f13c54SKadir Cetinkaya   (void)Dummy;
185d1f13c54SKadir Cetinkaya }
186d1f13c54SKadir Cetinkaya 
1871285172cSViktoriia Bakalova std::vector<Header> Header::all(Lang L) {
1880bf58458SHaojian Wu   ensureInitialized();
189e1aaa314SSam McCall   std::vector<Header> Result;
1901285172cSViktoriia Bakalova   const auto *Mapping = getMappingPerLang(L);
1911285172cSViktoriia Bakalova   Result.reserve(Mapping->HeaderIDs->size());
1921285172cSViktoriia Bakalova   for (unsigned I = 0, E = Mapping->HeaderIDs->size(); I < E; ++I)
1931285172cSViktoriia Bakalova     Result.push_back(Header(I, L));
194e1aaa314SSam McCall   return Result;
195e1aaa314SSam McCall }
1961285172cSViktoriia Bakalova std::optional<Header> Header::named(llvm::StringRef Name, Lang L) {
197d1f13c54SKadir Cetinkaya   ensureInitialized();
1981285172cSViktoriia Bakalova   const auto *Mapping = getMappingPerLang(L);
1991285172cSViktoriia Bakalova   auto It = Mapping->HeaderIDs->find(Name);
2001285172cSViktoriia Bakalova   if (It == Mapping->HeaderIDs->end())
2015891420eSKazu Hirata     return std::nullopt;
2021285172cSViktoriia Bakalova   return Header(It->second, L);
203d1f13c54SKadir Cetinkaya }
2041285172cSViktoriia Bakalova llvm::StringRef Header::name() const {
2051285172cSViktoriia Bakalova   return getMappingPerLang(Language)->HeaderNames[ID];
2061285172cSViktoriia Bakalova }
207e1aaa314SSam McCall 
2081285172cSViktoriia Bakalova std::vector<Symbol> Symbol::all(Lang L) {
2090bf58458SHaojian Wu   ensureInitialized();
210e1aaa314SSam McCall   std::vector<Symbol> Result;
2111285172cSViktoriia Bakalova   const auto *Mapping = getMappingPerLang(L);
2121285172cSViktoriia Bakalova   Result.reserve(Mapping->SymbolCount);
2131285172cSViktoriia Bakalova   for (unsigned I = 0, E = Mapping->SymbolCount; I < E; ++I)
2141285172cSViktoriia Bakalova     Result.push_back(Symbol(I, L));
215e1aaa314SSam McCall   return Result;
216e1aaa314SSam McCall }
217e1aaa314SSam McCall llvm::StringRef Symbol::scope() const {
218d46d44e3SHaojian Wu   return getMappingPerLang(Language)->SymbolNames[ID].scope();
219e1aaa314SSam McCall }
220e1aaa314SSam McCall llvm::StringRef Symbol::name() const {
221d46d44e3SHaojian Wu   return getMappingPerLang(Language)->SymbolNames[ID].name();
222e1aaa314SSam McCall }
223d46d44e3SHaojian Wu llvm::StringRef Symbol::qualifiedName() const {
224d46d44e3SHaojian Wu   return getMappingPerLang(Language)->SymbolNames[ID].qualifiedName();
225e1aaa314SSam McCall }
2261285172cSViktoriia Bakalova std::optional<Symbol> Symbol::named(llvm::StringRef Scope, llvm::StringRef Name,
2271285172cSViktoriia Bakalova                                     Lang L) {
228d1f13c54SKadir Cetinkaya   ensureInitialized();
2291285172cSViktoriia Bakalova 
2301285172cSViktoriia Bakalova   if (NSSymbolMap *NSSymbols =
2311285172cSViktoriia Bakalova           getMappingPerLang(L)->NamespaceSymbols->lookup(Scope)) {
232d1f13c54SKadir Cetinkaya     auto It = NSSymbols->find(Name);
233d1f13c54SKadir Cetinkaya     if (It != NSSymbols->end())
2341285172cSViktoriia Bakalova       return Symbol(It->second, L);
235d1f13c54SKadir Cetinkaya   }
2365891420eSKazu Hirata   return std::nullopt;
237d1f13c54SKadir Cetinkaya }
2385a623c2aSKadir Cetinkaya std::optional<Header> Symbol::header() const {
2395a623c2aSKadir Cetinkaya   const auto& Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];
2405a623c2aSKadir Cetinkaya   if (Headers.empty())
2415a623c2aSKadir Cetinkaya     return std::nullopt;
2425a623c2aSKadir Cetinkaya   return Header(Headers.front(), Language);
2431285172cSViktoriia Bakalova }
244d1f13c54SKadir Cetinkaya llvm::SmallVector<Header> Symbol::headers() const {
2451ab62d9dSHaojian Wu   llvm::SmallVector<Header> Results;
2461ab62d9dSHaojian Wu   for (auto HeaderID : getMappingPerLang(Language)->SymbolHeaderIDs[ID])
2471ab62d9dSHaojian Wu     Results.emplace_back(Header(HeaderID, Language));
2481ab62d9dSHaojian Wu   return Results;
249d1f13c54SKadir Cetinkaya }
250d1f13c54SKadir Cetinkaya 
251d1f13c54SKadir Cetinkaya Recognizer::Recognizer() { ensureInitialized(); }
252d1f13c54SKadir Cetinkaya 
253c812ab73SHaojian Wu NSSymbolMap *Recognizer::namespaceSymbols(const DeclContext *DC, Lang L) {
254c812ab73SHaojian Wu   if (DC->isTranslationUnit()) // global scope.
255c812ab73SHaojian Wu     return getMappingPerLang(L)->NamespaceSymbols->lookup("");
2561285172cSViktoriia Bakalova 
257c812ab73SHaojian Wu   auto It = NamespaceCache.find(DC);
258d1f13c54SKadir Cetinkaya   if (It != NamespaceCache.end())
259d1f13c54SKadir Cetinkaya     return It->second;
260c812ab73SHaojian Wu   const NamespaceDecl *D = llvm::cast<NamespaceDecl>(DC);
261d1f13c54SKadir Cetinkaya   NSSymbolMap *Result = [&]() -> NSSymbolMap * {
2621285172cSViktoriia Bakalova     if (D->isAnonymousNamespace())
263d1f13c54SKadir Cetinkaya       return nullptr;
264d1f13c54SKadir Cetinkaya     // Print the namespace and its parents ommitting inline scopes.
265d1f13c54SKadir Cetinkaya     std::string Scope;
266d1f13c54SKadir Cetinkaya     for (const auto *ND = D; ND;
267d1f13c54SKadir Cetinkaya          ND = llvm::dyn_cast_or_null<NamespaceDecl>(ND->getParent()))
268d1f13c54SKadir Cetinkaya       if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace())
269d1f13c54SKadir Cetinkaya         Scope = ND->getName().str() + "::" + Scope;
270c812ab73SHaojian Wu     return getMappingPerLang(L)->NamespaceSymbols->lookup(Scope);
271d1f13c54SKadir Cetinkaya   }();
272d1f13c54SKadir Cetinkaya   NamespaceCache.try_emplace(D, Result);
273d1f13c54SKadir Cetinkaya   return Result;
274d1f13c54SKadir Cetinkaya }
275d1f13c54SKadir Cetinkaya 
27667b72a28SHaojian Wu std::optional<Symbol> Recognizer::operator()(const Decl *D) {
277c812ab73SHaojian Wu   Lang L;
278e93cbd18SHaojian Wu   if (D->getLangOpts().CPlusPlus)
279c812ab73SHaojian Wu     L = Lang::CXX;
280e93cbd18SHaojian Wu   else if (D->getLangOpts().C99)
281c812ab73SHaojian Wu     L = Lang::C;
282e93cbd18SHaojian Wu   else
283c812ab73SHaojian Wu     return std::nullopt; // not a supported language.
284c812ab73SHaojian Wu 
285d1f13c54SKadir Cetinkaya   // If D is std::vector::iterator, `vector` is the outer symbol to look up.
286d1f13c54SKadir Cetinkaya   // We keep all the candidate DCs as some may turn out to be anon enums.
287d1f13c54SKadir Cetinkaya   // Do this resolution lazily as we may turn out not to have a std namespace.
288d1f13c54SKadir Cetinkaya   llvm::SmallVector<const DeclContext *> IntermediateDecl;
289d1f13c54SKadir Cetinkaya   const DeclContext *DC = D->getDeclContext();
290c812ab73SHaojian Wu   if (!DC) // The passed D is a TranslationUnitDecl!
291c812ab73SHaojian Wu     return std::nullopt;
292c812ab73SHaojian Wu   while (!DC->isNamespace() && !DC->isTranslationUnit()) {
293d1f13c54SKadir Cetinkaya     if (NamedDecl::classofKind(DC->getDeclKind()))
294d1f13c54SKadir Cetinkaya       IntermediateDecl.push_back(DC);
295d1f13c54SKadir Cetinkaya     DC = DC->getParent();
296d1f13c54SKadir Cetinkaya   }
297c812ab73SHaojian Wu   NSSymbolMap *Symbols = namespaceSymbols(DC, L);
298d1f13c54SKadir Cetinkaya   if (!Symbols)
2995891420eSKazu Hirata     return std::nullopt;
300d1f13c54SKadir Cetinkaya 
301d1f13c54SKadir Cetinkaya   llvm::StringRef Name = [&]() -> llvm::StringRef {
302d1f13c54SKadir Cetinkaya     for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {
303d1f13c54SKadir Cetinkaya       DeclarationName N = cast<NamedDecl>(SymDC)->getDeclName();
304d1f13c54SKadir Cetinkaya       if (const auto *II = N.getAsIdentifierInfo())
305d1f13c54SKadir Cetinkaya         return II->getName();
306d1f13c54SKadir Cetinkaya       if (!N.isEmpty())
307d1f13c54SKadir Cetinkaya         return ""; // e.g. operator<: give up
308d1f13c54SKadir Cetinkaya     }
309d1f13c54SKadir Cetinkaya     if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
310d1f13c54SKadir Cetinkaya       if (const auto *II = ND->getIdentifier())
311d1f13c54SKadir Cetinkaya         return II->getName();
312d1f13c54SKadir Cetinkaya     return "";
313d1f13c54SKadir Cetinkaya   }();
314d1f13c54SKadir Cetinkaya   if (Name.empty())
3155891420eSKazu Hirata     return std::nullopt;
316d1f13c54SKadir Cetinkaya 
317d1f13c54SKadir Cetinkaya   auto It = Symbols->find(Name);
318d1f13c54SKadir Cetinkaya   if (It == Symbols->end())
3195891420eSKazu Hirata     return std::nullopt;
320c812ab73SHaojian Wu   return Symbol(It->second, L);
321d1f13c54SKadir Cetinkaya }
322d1f13c54SKadir Cetinkaya 
323d1f13c54SKadir Cetinkaya } // namespace stdlib
324d1f13c54SKadir Cetinkaya } // namespace tooling
325d1f13c54SKadir Cetinkaya } // namespace clang
326