VitaNuo updated this revision to Diff 494329.
VitaNuo added a comment.
Address review comments.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D142992/new/
https://reviews.llvm.org/D142992
Files:
clang/include/clang/Tooling/Inclusions/StandardLibrary.h
clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
clang/unittests/Tooling/StandardLibraryTest.cpp
Index: clang/unittests/Tooling/StandardLibraryTest.cpp
===================================================================
--- clang/unittests/Tooling/StandardLibraryTest.cpp
+++ clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -38,14 +38,28 @@
EXPECT_EQ(llvm::to_string(*VectorH), "<vector>");
EXPECT_FALSE(stdlib::Header::named("HeadersTests.cpp"));
+ EXPECT_TRUE(stdlib::Header::named("<vector>", stdlib::Lang::CXX));
+ EXPECT_FALSE(stdlib::Header::named("<vector>", stdlib::Lang::C));
+
auto Vector = stdlib::Symbol::named("std::", "vector");
EXPECT_TRUE(Vector);
EXPECT_EQ(llvm::to_string(*Vector), "std::vector");
EXPECT_FALSE(stdlib::Symbol::named("std::", "dongle"));
EXPECT_FALSE(stdlib::Symbol::named("clang::", "ASTContext"));
+ EXPECT_TRUE(stdlib::Symbol::named("std::", "vector", stdlib::Lang::CXX));
+ EXPECT_FALSE(stdlib::Symbol::named("std::", "vector", stdlib::Lang::C));
+
EXPECT_EQ(Vector->header(), *VectorH);
EXPECT_THAT(Vector->headers(), ElementsAre(*VectorH));
+
+ EXPECT_FALSE(stdlib::Header::named("<stdint.h>"));
+ EXPECT_FALSE(stdlib::Header::named("<stdint.h>", stdlib::Lang::CXX));
+ EXPECT_TRUE(stdlib::Header::named("<stdint.h>", stdlib::Lang::C));
+
+ EXPECT_FALSE(stdlib::Symbol::named("", "int16_t"));
+ EXPECT_FALSE(stdlib::Symbol::named("", "int16_t", stdlib::Lang::CXX));
+ EXPECT_TRUE(stdlib::Symbol::named("", "int16_t", stdlib::Lang::C));
}
TEST(StdlibTest, Recognizer) {
@@ -96,10 +110,14 @@
EXPECT_EQ(Recognizer(&VectorNonstd), std::nullopt);
EXPECT_EQ(Recognizer(Vec), stdlib::Symbol::named("std::", "vector"));
+ EXPECT_EQ(Recognizer(Vec),
+ stdlib::Symbol::named("std::", "vector", stdlib::Lang::CXX));
EXPECT_EQ(Recognizer(Nest), stdlib::Symbol::named("std::", "vector"));
EXPECT_EQ(Recognizer(Clock),
stdlib::Symbol::named("std::chrono::", "system_clock"));
EXPECT_EQ(Recognizer(CDivT), stdlib::Symbol::named("", "div_t"));
+ EXPECT_EQ(Recognizer(CDivT),
+ stdlib::Symbol::named("", "div_t", stdlib::Lang::C));
EXPECT_EQ(Recognizer(Sec), std::nullopt);
}
Index: clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
===================================================================
--- clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -8,42 +8,69 @@
#include "clang/Tooling/Inclusions/StandardLibrary.h"
#include "clang/AST/Decl.h"
+#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace tooling {
namespace stdlib {
-static llvm::StringRef *HeaderNames;
-static std::pair<llvm::StringRef, llvm::StringRef> *SymbolNames;
-static unsigned *SymbolHeaderIDs;
-static llvm::DenseMap<llvm::StringRef, unsigned> *HeaderIDs;
+Lang &operator++(Lang &Language) {
+ Language = static_cast<Lang>(static_cast<unsigned>(Language) + 1);
+ return Language;
+}
+
// Maps symbol name -> Symbol::ID, within a namespace.
using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
-static llvm::DenseMap<llvm::StringRef, NSSymbolMap *> *NamespaceSymbols;
-static int initialize() {
+struct SymbolHeaderMapping {
+ llvm::StringRef *HeaderNames;
+ std::pair<llvm::StringRef, llvm::StringRef> *SymbolNames;
+ unsigned *SymbolHeaderIDs;
+ llvm::DenseMap<llvm::StringRef, unsigned> HeaderIDs;
+ llvm::DenseMap<llvm::StringRef, NSSymbolMap *> NamespaceSymbols;
+};
+
+static SymbolHeaderMapping
+ *LanguageMappings[static_cast<unsigned>(Lang::LastValue) + 1];
+
+static int countSymbols(Lang Language) {
unsigned SymCount = 0;
#define SYMBOL(Name, NS, Header) ++SymCount;
+ switch (Language) {
+ case Lang::C:
#include "clang/Tooling/Inclusions/CSymbolMap.inc"
+ break;
+ case Lang::CXX:
#include "clang/Tooling/Inclusions/StdSymbolMap.inc"
+ break;
+ }
#undef SYMBOL
- SymbolNames = new std::remove_reference_t<decltype(*SymbolNames)>[SymCount];
- SymbolHeaderIDs =
- new std::remove_reference_t<decltype(*SymbolHeaderIDs)>[SymCount];
- NamespaceSymbols = new std::remove_reference_t<decltype(*NamespaceSymbols)>;
- HeaderIDs = new std::remove_reference_t<decltype(*HeaderIDs)>;
+ return SymCount;
+}
+
+static void initialize(Lang Language) {
+ SymbolHeaderMapping *Mapping = new SymbolHeaderMapping();
+ LanguageMappings[static_cast<unsigned>(Language)] = Mapping;
+
+ unsigned SymCount = countSymbols(Language);
+ Mapping->SymbolNames =
+ new std::remove_reference_t<decltype(*Mapping->SymbolNames)>[SymCount];
+ Mapping->SymbolHeaderIDs = new std::remove_reference_t<
+ decltype(*Mapping->SymbolHeaderIDs)>[SymCount];
auto AddNS = [&](llvm::StringRef NS) -> NSSymbolMap & {
- auto R = NamespaceSymbols->try_emplace(NS, nullptr);
+ auto R = Mapping->NamespaceSymbols.try_emplace(NS, nullptr);
if (R.second)
R.first->second = new NSSymbolMap();
return *R.first->second;
};
auto AddHeader = [&](llvm::StringRef Header) -> unsigned {
- return HeaderIDs->try_emplace(Header, HeaderIDs->size()).first->second;
+ return Mapping->HeaderIDs.try_emplace(Header, Mapping->HeaderIDs.size())
+ .first->second;
};
auto Add = [&, SymIndex(0)](llvm::StringRef Name, llvm::StringRef NS,
@@ -51,8 +78,8 @@
if (NS == "None")
NS = "";
- SymbolNames[SymIndex] = {NS, Name};
- SymbolHeaderIDs[SymIndex] = AddHeader(HeaderName);
+ Mapping->SymbolNames[SymIndex] = {NS, Name};
+ Mapping->SymbolHeaderIDs[SymIndex] = AddHeader(HeaderName);
NSSymbolMap &NSSymbols = AddNS(NS);
NSSymbols.try_emplace(Name, SymIndex);
@@ -60,14 +87,24 @@
++SymIndex;
};
#define SYMBOL(Name, NS, Header) Add(#Name, #NS, #Header);
+ switch (Language) {
+ case Lang::C:
#include "clang/Tooling/Inclusions/CSymbolMap.inc"
+ break;
+ case Lang::CXX:
#include "clang/Tooling/Inclusions/StdSymbolMap.inc"
+ break;
+ }
#undef SYMBOL
- HeaderNames = new llvm::StringRef[HeaderIDs->size()];
- for (const auto &E : *HeaderIDs)
- HeaderNames[E.second] = E.first;
+ Mapping->HeaderNames = new llvm::StringRef[Mapping->HeaderIDs.size()];
+ for (const auto &E : Mapping->HeaderIDs)
+ Mapping->HeaderNames[E.second] = E.first;
+}
+static int initialize() {
+ for (Lang i = Lang::C; i <= Lang::LastValue; ++i)
+ initialize(i);
return 0;
}
@@ -76,38 +113,63 @@
(void)Dummy;
}
-std::optional<Header> Header::named(llvm::StringRef Name) {
+std::optional<Header> Header::named(llvm::StringRef Name, Lang Language) {
ensureInitialized();
- auto It = HeaderIDs->find(Name);
- if (It == HeaderIDs->end())
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ auto It = Mapping->HeaderIDs.find(Name);
+ if (It == Mapping->HeaderIDs.end())
return std::nullopt;
- return Header(It->second);
+ return Header(It->second, Language);
+}
+
+llvm::StringRef Header::name() const {
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ return Mapping->HeaderNames[ID];
+}
+llvm::StringRef Symbol::scope() const {
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ return Mapping->SymbolNames[ID].first;
}
-llvm::StringRef Header::name() const { return HeaderNames[ID]; }
-llvm::StringRef Symbol::scope() const { return SymbolNames[ID].first; }
-llvm::StringRef Symbol::name() const { return SymbolNames[ID].second; }
-std::optional<Symbol> Symbol::named(llvm::StringRef Scope,
- llvm::StringRef Name) {
+llvm::StringRef Symbol::name() const {
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ return Mapping->SymbolNames[ID].second;
+}
+std::optional<Symbol> Symbol::named(llvm::StringRef Scope, llvm::StringRef Name,
+ Lang Language) {
ensureInitialized();
- if (NSSymbolMap *NSSymbols = NamespaceSymbols->lookup(Scope)) {
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ if (NSSymbolMap *NSSymbols = Mapping->NamespaceSymbols.lookup(Scope)) {
auto It = NSSymbols->find(Name);
if (It != NSSymbols->end())
- return Symbol(It->second);
+ return Symbol(It->second, Language);
}
return std::nullopt;
}
-Header Symbol::header() const { return Header(SymbolHeaderIDs[ID]); }
+Header Symbol::header() const {
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+ return Header(Mapping->SymbolHeaderIDs[ID], Language);
+}
llvm::SmallVector<Header> Symbol::headers() const {
return {header()}; // FIXME: multiple in case of ambiguity
}
Recognizer::Recognizer() { ensureInitialized(); }
-NSSymbolMap *Recognizer::namespaceSymbols(const NamespaceDecl *D) {
+NSSymbolMap *Recognizer::namespaceSymbols(const NamespaceDecl *D,
+ Lang Language) {
auto It = NamespaceCache.find(D);
if (It != NamespaceCache.end())
return It->second;
+ SymbolHeaderMapping *Mapping =
+ LanguageMappings[static_cast<unsigned>(Language)];
+
NSSymbolMap *Result = [&]() -> NSSymbolMap * {
if (D && D->isAnonymousNamespace())
return nullptr;
@@ -117,13 +179,18 @@
ND = llvm::dyn_cast_or_null<NamespaceDecl>(ND->getParent()))
if (!ND->isInlineNamespace() && !ND->isAnonymousNamespace())
Scope = ND->getName().str() + "::" + Scope;
- return NamespaceSymbols->lookup(Scope);
+ return Mapping->NamespaceSymbols.lookup(Scope);
}();
NamespaceCache.try_emplace(D, Result);
return Result;
}
std::optional<Symbol> Recognizer::operator()(const Decl *D) {
+ Lang RecognizerLang = Lang::C;
+ if (D->getLangOpts().CPlusPlus) {
+ RecognizerLang = Lang::CXX;
+ }
+
// If D is std::vector::iterator, `vector` is the outer symbol to look up.
// We keep all the candidate DCs as some may turn out to be anon enums.
// Do this resolution lazily as we may turn out not to have a std namespace.
@@ -134,7 +201,8 @@
IntermediateDecl.push_back(DC);
DC = DC->getParent();
}
- NSSymbolMap *Symbols = namespaceSymbols(cast_or_null<NamespaceDecl>(DC));
+ NSSymbolMap *Symbols =
+ namespaceSymbols(cast_or_null<NamespaceDecl>(DC), RecognizerLang);
if (!Symbols)
return std::nullopt;
Index: clang/include/clang/Tooling/Inclusions/StandardLibrary.h
===================================================================
--- clang/include/clang/Tooling/Inclusions/StandardLibrary.h
+++ clang/include/clang/Tooling/Inclusions/StandardLibrary.h
@@ -30,6 +30,7 @@
namespace stdlib {
class Symbol;
+enum class Lang { C = 0, CXX, LastValue = CXX };
// A standard library header, such as <iostream>
// Lightweight class, in fact just an index into a table.
@@ -38,7 +39,8 @@
class Header {
public:
// Name should contain the angle brackets, e.g. "<vector>".
- static std::optional<Header> named(llvm::StringRef Name);
+ static std::optional<Header> named(llvm::StringRef Name,
+ Lang Language = Lang::CXX);
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Header &H) {
return OS << H.name();
@@ -46,8 +48,10 @@
llvm::StringRef name() const;
private:
- Header(unsigned ID) : ID(ID) {}
+ Header(unsigned ID, Lang Language = Lang::CXX) : ID(ID), Language(Language) {}
unsigned ID;
+ Lang Language;
+
friend Symbol;
friend llvm::DenseMapInfo<Header>;
friend bool operator==(const Header &L, const Header &R) {
@@ -65,8 +69,8 @@
public:
/// \p Scope should have the trailing "::", for example:
/// named("std::chrono::", "system_clock")
- static std::optional<Symbol> named(llvm::StringRef Scope,
- llvm::StringRef Name);
+ static std::optional<Symbol>
+ named(llvm::StringRef Scope, llvm::StringRef Name, Lang Language = Lang::CXX);
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
return OS << S.scope() << S.name();
@@ -79,8 +83,9 @@
llvm::SmallVector<Header> headers() const;
private:
- Symbol(unsigned ID) : ID(ID) {}
+ Symbol(unsigned ID, Lang Language = Lang::CXX) : ID(ID), Language(Language) {}
unsigned ID;
+ clang::tooling::stdlib::Lang Language;
friend class Recognizer;
friend llvm::DenseMapInfo<Symbol>;
friend bool operator==(const Symbol &L, const Symbol &R) {
@@ -99,7 +104,8 @@
private:
using NSSymbolMap = llvm::DenseMap<llvm::StringRef, unsigned>;
- NSSymbolMap *namespaceSymbols(const NamespaceDecl *D);
+ NSSymbolMap *namespaceSymbols(const NamespaceDecl *D,
+ Lang Language = Lang::CXX);
llvm::DenseMap<const DeclContext *, NSSymbolMap *> NamespaceCache;
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits