ilya-biryukov created this revision.
ilya-biryukov added reviewers: sammccall, hokein.
Herald added subscribers: jfb, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

This takes ~5% of time when running clangd unit tests.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67172

Files:
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/Preamble.cpp
  clang-tools-extra/clangd/index/CanonicalIncludes.cpp
  clang-tools-extra/clangd/index/CanonicalIncludes.h
  clang-tools-extra/clangd/index/IndexAction.cpp
  clang-tools-extra/clangd/unittests/CanonicalIncludesTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -973,7 +973,7 @@
   CanonicalIncludes Includes;
   auto Language = LangOptions();
   Language.CPlusPlus = true;
-  addSystemHeadersMapping(&Includes, Language);
+  Includes.addSystemHeadersMapping(Language);
   CollectorOpts.Includes = &Includes;
   runSymbolCollector("namespace std { class string {}; }", /*Main=*/"");
   EXPECT_THAT(Symbols,
Index: clang-tools-extra/clangd/unittests/CanonicalIncludesTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CanonicalIncludesTests.cpp
+++ clang-tools-extra/clangd/unittests/CanonicalIncludesTests.cpp
@@ -17,7 +17,7 @@
   CanonicalIncludes CI;
   auto Language = LangOptions();
   Language.C11 = true;
-  addSystemHeadersMapping(&CI, Language);
+  CI.addSystemHeadersMapping(Language);
   // Usual standard library symbols are mapped correctly.
   EXPECT_EQ("<stdio.h>", CI.mapHeader("path/stdio.h", "printf"));
 }
@@ -26,7 +26,7 @@
   CanonicalIncludes CI;
   auto Language = LangOptions();
   Language.CPlusPlus = true;
-  addSystemHeadersMapping(&CI, Language);
+  CI.addSystemHeadersMapping(Language);
 
   // Usual standard library symbols are mapped correctly.
   EXPECT_EQ("<vector>", CI.mapHeader("path/vector.h", "std::vector"));
Index: clang-tools-extra/clangd/index/IndexAction.cpp
===================================================================
--- clang-tools-extra/clangd/index/IndexAction.cpp
+++ clang-tools-extra/clangd/index/IndexAction.cpp
@@ -140,7 +140,7 @@
   std::unique_ptr<ASTConsumer>
   CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
     CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
-    addSystemHeadersMapping(Includes.get(), CI.getLangOpts());
+    Includes->addSystemHeadersMapping(CI.getLangOpts());
     if (IncludeGraphCallback != nullptr)
       CI.getPreprocessor().addPPCallbacks(
           std::make_unique<IncludeGraphCollector>(CI.getSourceManager(), IG));
Index: clang-tools-extra/clangd/index/CanonicalIncludes.h
===================================================================
--- clang-tools-extra/clangd/index/CanonicalIncludes.h
+++ clang-tools-extra/clangd/index/CanonicalIncludes.h
@@ -55,6 +55,16 @@
   llvm::StringRef mapHeader(llvm::StringRef Header,
                             llvm::StringRef QualifiedName) const;
 
+  /// Adds mapping for system headers and some special symbols (e.g. STL symbols
+  /// in <iosfwd> need to be mapped individually). Approximately, the following
+  /// system headers are handled:
+  ///   - C++ standard library e.g. bits/basic_string.h$ -> <string>
+  ///   - Posix library e.g. bits/pthreadtypes.h$ -> <pthread.h>
+  ///   - Compiler extensions, e.g. include/avx512bwintrin.h$ -> <immintrin.h>
+  /// The mapping is hardcoded and hand-maintained, so it might not cover all
+  /// headers.
+  void addSystemHeadersMapping(const LangOptions &Language);
+
 private:
   /// A map from full include path to a canonical path.
   llvm::StringMap<std::string> FullPathMapping;
@@ -65,6 +75,8 @@
   int MaxSuffixComponents = 0;
   /// A map from fully qualified symbol names to header names.
   llvm::StringMap<std::string> SymbolMapping;
+  /// Precomputed mapping of std symbols. Ignored when null.
+  const CanonicalIncludes *SystemSymbols = nullptr;
 };
 
 /// Returns a CommentHandler that parses pragma comment on include files to
@@ -76,16 +88,6 @@
 std::unique_ptr<CommentHandler>
 collectIWYUHeaderMaps(CanonicalIncludes *Includes);
 
-/// Adds mapping for system headers and some special symbols (e.g. STL symbols
-/// in <iosfwd> need to be mapped individually). Approximately, the following
-/// system headers are handled:
-///   - C++ standard library e.g. bits/basic_string.h$ -> <string>
-///   - Posix library e.g. bits/pthreadtypes.h$ -> <pthread.h>
-///   - Compiler extensions, e.g. include/avx512bwintrin.h$ -> <immintrin.h>
-/// The mapping is hardcoded and hand-maintained, so it might not cover all
-/// headers.
-void addSystemHeadersMapping(CanonicalIncludes *Includes,
-                             const LangOptions &Language);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/index/CanonicalIncludes.cpp
===================================================================
--- clang-tools-extra/clangd/index/CanonicalIncludes.cpp
+++ clang-tools-extra/clangd/index/CanonicalIncludes.cpp
@@ -8,9 +8,12 @@
 
 #include "CanonicalIncludes.h"
 #include "Headers.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Driver/Types.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
 #include <algorithm>
+#include <memory>
 
 namespace clang {
 namespace clangd {
@@ -40,6 +43,12 @@
 CanonicalIncludes::mapHeader(llvm::StringRef Header,
                              llvm::StringRef QualifiedName) const {
   assert(!Header.empty());
+  // Prefer a mapping from the system symbols.
+  if (SystemSymbols) {
+    auto Result = SystemSymbols->mapHeader(Header, QualifiedName);
+    if (Result != Header)
+      return Result;
+  }
   auto SE = SymbolMapping.find(QualifiedName);
   if (SE != SymbolMapping.end())
     return SE->second;
@@ -86,24 +95,41 @@
   return std::make_unique<PragmaCommentHandler>(Includes);
 }
 
-void addSystemHeadersMapping(CanonicalIncludes *Includes,
-                             const LangOptions &Language) {
+namespace {
+enum class SymbolsFlavour { Cpp, C11, Other };
+
+SymbolsFlavour symbolsFlavour(const LangOptions &Language) {
+  if (Language.CPlusPlus)
+    return SymbolsFlavour::Cpp;
+  if (Language.C11)
+    return SymbolsFlavour::C11;
+  return SymbolsFlavour::Other;
+}
+
+std::unique_ptr<CanonicalIncludes>
+buildStandardSymbolMapping(SymbolsFlavour Language) {
+  auto Includes = std::make_unique<CanonicalIncludes>();
   static constexpr std::pair<const char *, const char *> SymbolMap[] = {
-#define SYMBOL(Name, NameSpace, Header) { #NameSpace#Name, #Header },
-      #include "StdSymbolMap.inc"
+#define SYMBOL(Name, NameSpace, Header) {#NameSpace #Name, #Header},
+#include "StdSymbolMap.inc"
 #undef SYMBOL
   };
   static constexpr std::pair<const char *, const char *> CSymbolMap[] = {
-#define SYMBOL(Name, NameSpace, Header) { #Name, #Header },
-      #include "CSymbolMap.inc"
+#define SYMBOL(Name, NameSpace, Header) {#Name, #Header},
+#include "CSymbolMap.inc"
 #undef SYMBOL
   };
-  if (Language.CPlusPlus) {
+  switch (Language) {
+  case SymbolsFlavour::Cpp:
     for (const auto &Pair : SymbolMap)
       Includes->addSymbolMapping(Pair.first, Pair.second);
-  } else if (Language.C11) {
+    break;
+  case SymbolsFlavour::C11:
     for (const auto &Pair : CSymbolMap)
       Includes->addSymbolMapping(Pair.first, Pair.second);
+    break;
+  case SymbolsFlavour::Other:
+    break;
   }
   // FIXME: remove the std header mapping once we support ambiguous symbols, now
   // it serves as a fallback to disambiguate:
@@ -763,6 +789,32 @@
   };
   for (const auto &Pair : SystemHeaderMap)
     Includes->addPathSuffixMapping(Pair.first, Pair.second);
+  return Includes;
+}
+
+const CanonicalIncludes &getStandardSymbolMapping(const LangOptions &Opts) {
+  static const CanonicalIncludes *ForCpp =
+      buildStandardSymbolMapping(SymbolsFlavour::Cpp).release();
+  static const CanonicalIncludes *ForC11 =
+      buildStandardSymbolMapping(SymbolsFlavour::C11).release();
+  static const CanonicalIncludes *ForOther =
+      buildStandardSymbolMapping(SymbolsFlavour::Other).release();
+
+  switch (symbolsFlavour(Opts)) {
+  case SymbolsFlavour::Cpp:
+    return *ForCpp;
+  case SymbolsFlavour::C11:
+    return *ForC11;
+  case SymbolsFlavour::Other:
+    return *ForOther;
+  }
+  llvm_unreachable("unhandled SymbolFlavour");
+}
+} // namespace
+
+void CanonicalIncludes::addSystemHeadersMapping(const LangOptions &Language) {
+  assert(SystemSymbols == nullptr && "resetting the system headers mapping");
+  SystemSymbols = &getStandardSymbolMapping(Language);
 }
 
 } // namespace clangd
Index: clang-tools-extra/clangd/Preamble.cpp
===================================================================
--- clang-tools-extra/clangd/Preamble.cpp
+++ clang-tools-extra/clangd/Preamble.cpp
@@ -78,7 +78,7 @@
   }
 
   void BeforeExecute(CompilerInstance &CI) override {
-    addSystemHeadersMapping(&CanonIncludes, CI.getLangOpts());
+    CanonIncludes.addSystemHeadersMapping(CI.getLangOpts());
     SourceMgr = &CI.getSourceManager();
   }
 
Index: clang-tools-extra/clangd/ParsedAST.cpp
===================================================================
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -368,7 +368,7 @@
   if (Preamble)
     CanonIncludes = Preamble->CanonIncludes;
   else
-    addSystemHeadersMapping(&CanonIncludes, Clang->getLangOpts());
+    CanonIncludes.addSystemHeadersMapping(Clang->getLangOpts());
   std::unique_ptr<CommentHandler> IWYUHandler =
       collectIWYUHeaderMaps(&CanonIncludes);
   Clang->getPreprocessor().addCommentHandler(IWYUHandler.get());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to