Forward declare FileEntry and DirectoryEntry in Module.h
authorReid Kleckner <rnk@google.com>
Thu, 27 Feb 2020 00:29:37 +0000 (16:29 -0800)
committerReid Kleckner <rnk@google.com>
Thu, 27 Feb 2020 18:18:06 +0000 (10:18 -0800)
FileManager.h is an expensive header (~350ms for me in isolation), so
try to do without it.

Notably, we need to avoid checking the alignment of FileEntry, which
happens for DenseMap<FileEntry*> and PointerUnion<FileEntry*>. I
adjusted the code to avoid PointerUnion, and moved the DenseMap
insertion to the .cpp file.

Globally, this only saved about ~17 includes of the related headers
because SourceManager.h still includes FileManager.h, and it is more
popular than Module.h.

clang/include/clang/Basic/Module.h
clang/include/clang/Serialization/ModuleFile.h
clang/lib/Basic/Module.cpp
clang/lib/Lex/ModuleMap.cpp

index 953d183..d2e7f84 100644 (file)
 #ifndef LLVM_CLANG_BASIC_MODULE_H
 #define LLVM_CLANG_BASIC_MODULE_H
 
-#include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/STLExtras.h"
@@ -44,6 +42,9 @@ class raw_ostream;
 
 namespace clang {
 
+class DirectoryEntry;
+class FileEntry;
+class FileManager;
 class LangOptions;
 class TargetInfo;
 
@@ -101,7 +102,7 @@ public:
   std::string PresumedModuleMapFile;
 
   /// The umbrella header or directory.
-  llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
+  const void *Umbrella = nullptr;
 
   /// The module signature.
   ASTFileSignature Signature;
@@ -268,6 +269,9 @@ public:
   /// to a regular (public) module map.
   unsigned ModuleMapIsPrivate : 1;
 
+  /// Whether Umbrella is a directory or header.
+  unsigned HasUmbrellaDir : 1;
+
   /// Describes the visibility of the various names within a
   /// particular module.
   enum NameVisibilityKind {
@@ -487,22 +491,18 @@ public:
   /// Retrieve the header that serves as the umbrella header for this
   /// module.
   Header getUmbrellaHeader() const {
-    if (auto *E = Umbrella.dyn_cast<const FileEntry *>())
-      return Header{UmbrellaAsWritten, E};
+    if (!HasUmbrellaDir)
+      return Header{UmbrellaAsWritten,
+                    static_cast<const FileEntry *>(Umbrella)};
     return Header{};
   }
 
   /// Determine whether this module has an umbrella directory that is
   /// not based on an umbrella header.
-  bool hasUmbrellaDir() const {
-    return Umbrella && Umbrella.is<const DirectoryEntry *>();
-  }
+  bool hasUmbrellaDir() const { return Umbrella && HasUmbrellaDir; }
 
   /// Add a top-level header associated with this module.
-  void addTopHeader(const FileEntry *File) {
-    assert(File);
-    TopHeaders.insert(File);
-  }
+  void addTopHeader(const FileEntry *File);
 
   /// Add a top-level header filename associated with this module.
   void addTopHeaderFilename(StringRef Filename) {
index 8f3eb02..90d2745 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_SERIALIZATION_MODULEFILE_H
 #define LLVM_CLANG_SERIALIZATION_MODULEFILE_H
 
+#include "clang/Basic/FileManager.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Serialization/ASTBitCodes.h"
@@ -34,8 +35,6 @@
 
 namespace clang {
 
-class FileEntry;
-
 namespace serialization {
 
 /// Specifies the kind of module that has been loaded.
index 92835c9..7fb6dee 100644 (file)
@@ -44,7 +44,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
       InferSubmodules(false), InferExplicitSubmodules(false),
       InferExportWildcard(false), ConfigMacrosExhaustive(false),
       NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
-      NameVisibility(Hidden) {
+      HasUmbrellaDir(false), NameVisibility(Hidden) {
   if (Parent) {
     if (!Parent->isAvailable())
       IsAvailable = false;
@@ -239,7 +239,12 @@ Module::DirectoryName Module::getUmbrellaDir() const {
   if (Header U = getUmbrellaHeader())
     return {"", U.Entry->getDir()};
 
-  return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
+  return {UmbrellaAsWritten, static_cast<const DirectoryEntry *>(Umbrella)};
+}
+
+void Module::addTopHeader(const FileEntry *File) {
+  assert(File);
+  TopHeaders.insert(File);
 }
 
 ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
index 6622339..1c340f3 100644 (file)
@@ -1105,6 +1105,7 @@ void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
                                   Twine NameAsWritten) {
   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
   Mod->Umbrella = UmbrellaHeader;
+  Mod->HasUmbrellaDir = false;
   Mod->UmbrellaAsWritten = NameAsWritten.str();
   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
 
@@ -1116,6 +1117,7 @@ void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
 void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
                                Twine NameAsWritten) {
   Mod->Umbrella = UmbrellaDir;
+  Mod->HasUmbrellaDir = true;
   Mod->UmbrellaAsWritten = NameAsWritten.str();
   UmbrellaDirs[UmbrellaDir] = Mod;
 }