dexonsmith updated this revision to Diff 302022.
dexonsmith edited the summary of this revision.
dexonsmith added a comment.

Removed the `FIXME`s about the `...AsWritten` fields, as I just took a deeper 
look and we need them. The headers/etc. are looked up in the `FileManager` with 
the module directory prepended, and these `...AsWritten` fields are without 
that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D90497/new/

https://reviews.llvm.org/D90497

Files:
  clang/include/clang/Basic/DirectoryEntry.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Lex/ModuleMap.h
  clang/lib/Basic/Module.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Serialization/ASTReader.cpp

Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -1921,7 +1921,8 @@
     // FIXME: This is not always the right filename-as-written, but we're not
     // going to use this information to rebuild the module, so it doesn't make
     // a lot of difference.
-    Module::Header H = {std::string(key.Filename), *FileMgr.getFile(Filename)};
+    Module::Header H = {std::string(key.Filename),
+                        *FileMgr.getFileRef(Filename)};
     ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
     HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
   }
@@ -5579,7 +5580,8 @@
     case SUBMODULE_UMBRELLA_HEADER: {
       std::string Filename = std::string(Blob);
       ResolveImportedPath(F, Filename);
-      if (auto Umbrella = PP.getFileManager().getFile(Filename)) {
+      if (auto Umbrella =
+              expectedToOptional(PP.getFileManager().getFileRef(Filename))) {
         if (!CurrentModule->getUmbrellaHeader())
           ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob);
         else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) {
@@ -5612,7 +5614,8 @@
     case SUBMODULE_UMBRELLA_DIR: {
       std::string Dirname = std::string(Blob);
       ResolveImportedPath(F, Dirname);
-      if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) {
+      if (auto Umbrella = expectedToOptional(
+              PP.getFileManager().getDirectoryRef(Dirname))) {
         if (!CurrentModule->getUmbrellaDir())
           ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob);
         else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) {
Index: clang/lib/Lex/ModuleMap.cpp
===================================================================
--- clang/lib/Lex/ModuleMap.cpp
+++ clang/lib/Lex/ModuleMap.cpp
@@ -300,7 +300,7 @@
   // supplied by Clang. Find that builtin header.
   SmallString<128> Path;
   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
-  auto File = SourceMgr.getFileManager().getFile(Path);
+  auto File = expectedToOptional(SourceMgr.getFileManager().getFileRef(Path));
   if (!File)
     return false;
 
@@ -1012,7 +1012,7 @@
   // Look for an umbrella header.
   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
-  auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
+  auto UmbrellaHeader = expectedToOptional(FileMgr.getFileRef(UmbrellaName));
 
   // FIXME: If there's no umbrella header, we could probably scan the
   // framework to load *everything*. But, it's not clear that this is a good
@@ -1121,21 +1121,21 @@
   return Result;
 }
 
-void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
+void ModuleMap::setUmbrellaHeader(Module *Mod, FileEntryRef UmbrellaHeader,
                                   Twine NameAsWritten) {
   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
-  Mod->Umbrella = UmbrellaHeader;
+  Mod->Umbrella = &UmbrellaHeader.getMapEntry();
   Mod->UmbrellaAsWritten = NameAsWritten.str();
-  UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
+  UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
 
   // Notify callbacks that we just added a new header.
   for (const auto &Cb : Callbacks)
     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
 }
 
-void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+void ModuleMap::setUmbrellaDir(Module *Mod, DirectoryEntryRef UmbrellaDir,
                                Twine NameAsWritten) {
-  Mod->Umbrella = UmbrellaDir;
+  Mod->Umbrella = &UmbrellaDir.getMapEntry();
   Mod->UmbrellaAsWritten = NameAsWritten.str();
   UmbrellaDirs[UmbrellaDir] = Mod;
 }
@@ -2416,15 +2416,17 @@
   }
 
   // Look for this file.
-  const DirectoryEntry *Dir = nullptr;
+  Optional<DirectoryEntryRef> Dir;
   if (llvm::sys::path::is_absolute(DirName)) {
-    if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
+    if (auto D = expectedToOptional(
+            SourceMgr.getFileManager().getDirectoryRef(DirName)))
       Dir = *D;
   } else {
     SmallString<128> PathName;
     PathName = Directory->getName();
     llvm::sys::path::append(PathName, DirName);
-    if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
+    if (auto D = expectedToOptional(
+            SourceMgr.getFileManager().getDirectoryRef(PathName)))
       Dir = *D;
   }
 
@@ -2445,7 +2447,8 @@
         SourceMgr.getFileManager().getVirtualFileSystem();
     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
          I != E && !EC; I.increment(EC)) {
-      if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
+      if (auto FE = expectedToOptional(
+              SourceMgr.getFileManager().getFileRef(I->path()))) {
         Module::Header Header = {std::string(I->path()), *FE};
         Headers.push_back(std::move(Header));
       }
@@ -2459,7 +2462,7 @@
     return;
   }
 
-  if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
+  if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
       << OwningModule->getFullModuleName();
     HadError = true;
@@ -2467,7 +2470,7 @@
   }
 
   // Record this umbrella directory.
-  Map.setUmbrellaDir(ActiveModule, Dir, DirName);
+  Map.setUmbrellaDir(ActiveModule, *Dir, DirName);
 }
 
 /// Parse a module export declaration.
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -298,7 +298,7 @@
         << Name;
       continue;
     }
-    Headers.push_back({std::string(Name), &FE->getFileEntry()});
+    Headers.push_back({std::string(Name), *FE});
   }
   HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
 
Index: clang/lib/Basic/Module.cpp
===================================================================
--- clang/lib/Basic/Module.cpp
+++ clang/lib/Basic/Module.cpp
@@ -247,7 +247,10 @@
   if (Header U = getUmbrellaHeader())
     return {"", U.Entry->getDir()};
 
-  return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
+  if (auto *ME = Umbrella.dyn_cast<const DirectoryEntryRef::MapEntry *>())
+    return {UmbrellaAsWritten, DirectoryEntryRef(*ME)};
+
+  return {"", None};
 }
 
 void Module::addTopHeader(const FileEntry *File) {
Index: clang/include/clang/Lex/ModuleMap.h
===================================================================
--- clang/include/clang/Lex/ModuleMap.h
+++ clang/include/clang/Lex/ModuleMap.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_LEX_MODULEMAP_H
 #define LLVM_CLANG_LEX_MODULEMAP_H
 
+#include "clang/Basic/FileEntry.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Module.h"
@@ -37,7 +38,6 @@
 
 class DiagnosticsEngine;
 class DirectoryEntry;
-class FileEntry;
 class FileManager;
 class HeaderSearch;
 class SourceManager;
@@ -648,12 +648,12 @@
 
   /// Sets the umbrella header of the given module to the given
   /// header.
-  void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
+  void setUmbrellaHeader(Module *Mod, FileEntryRef UmbrellaHeader,
                          Twine NameAsWritten);
 
   /// Sets the umbrella directory of the given module to the given
   /// directory.
-  void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+  void setUmbrellaDir(Module *Mod, DirectoryEntryRef UmbrellaDir,
                       Twine NameAsWritten);
 
   /// Adds this header to the given module.
Index: clang/include/clang/Basic/Module.h
===================================================================
--- clang/include/clang/Basic/Module.h
+++ clang/include/clang/Basic/Module.h
@@ -133,7 +133,9 @@
   std::string PresumedModuleMapFile;
 
   /// The umbrella header or directory.
-  llvm::PointerUnion<const FileEntry *, const DirectoryEntry *> Umbrella;
+  llvm::PointerUnion<const FileEntryRef::MapEntry *,
+                     const DirectoryEntryRef::MapEntry *>
+      Umbrella;
 
   /// The module signature.
   ASTFileSignature Signature;
@@ -188,18 +190,18 @@
   /// file.
   struct Header {
     std::string NameAsWritten;
-    const FileEntry *Entry;
+    OptionalFileEntryRefDegradesToFileEntryPtr Entry;
 
-    explicit operator bool() { return Entry; }
+    explicit operator bool() { return Entry != None; }
   };
 
   /// Information about a directory name as found in the module map
   /// file.
   struct DirectoryName {
     std::string NameAsWritten;
-    const DirectoryEntry *Entry;
+    OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr Entry;
 
-    explicit operator bool() { return Entry; }
+    explicit operator bool() { return Entry != None; }
   };
 
   /// The headers that are part of this module.
@@ -544,15 +546,15 @@
   /// Retrieve the header that serves as the umbrella header for this
   /// module.
   Header getUmbrellaHeader() const {
-    if (auto *FE = Umbrella.dyn_cast<const FileEntry *>())
-      return Header{UmbrellaAsWritten, FE};
+    if (auto *ME = Umbrella.dyn_cast<const FileEntryRef::MapEntry *>())
+      return Header{UmbrellaAsWritten, FileEntryRef(*ME)};
     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 *>();
+    return Umbrella && Umbrella.is<const DirectoryEntryRef::MapEntry *>();
   }
 
   /// Add a top-level header associated with this module.
Index: clang/include/clang/Basic/DirectoryEntry.h
===================================================================
--- clang/include/clang/Basic/DirectoryEntry.h
+++ clang/include/clang/Basic/DirectoryEntry.h
@@ -51,7 +51,26 @@
   const MapEntry &getMapEntry() const { return *ME; }
 
   DirectoryEntryRef() = delete;
-  DirectoryEntryRef(MapEntry &ME) : ME(&ME) {}
+  DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
+
+  /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
+  /// facilitate incremental adoption.
+  ///
+  /// The goal is to avoid code churn due to dances like the following:
+  /// \code
+  /// // Old code.
+  /// lvalue = rvalue;
+  ///
+  /// // Temporary code from an incremental patch.
+  /// lvalue = &rvalue.getDirectoryEntry();
+  ///
+  /// // Final code.
+  /// lvalue = rvalue;
+  /// \endcode
+  ///
+  /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
+  /// has been deleted, delete this implicit conversion.
+  operator const DirectoryEntry *() const { return &getDirEntry(); }
 
 private:
   friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
@@ -147,4 +166,76 @@
 } // end namespace optional_detail
 } // end namespace llvm
 
+namespace clang {
+
+/// Wrapper around Optional<DirectoryEntryRef> that degrades to 'const
+/// DirectoryEntry*', facilitating incremental patches to propagate
+/// DirectoryEntryRef.
+///
+/// This class can be used as return value or field where it's convenient for
+/// an Optional<DirectoryEntryRef> to degrade to a 'const DirectoryEntry*'. The
+/// purpose is to avoid code churn due to dances like the following:
+/// \code
+/// // Old code.
+/// lvalue = rvalue;
+///
+/// // Temporary code from an incremental patch.
+/// Optional<DirectoryEntryRef> MaybeF = rvalue;
+/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
+///
+/// // Final code.
+/// lvalue = rvalue;
+/// \endcode
+///
+/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
+/// and DirectoryEntry::getName have been deleted, delete this class and
+/// replace instances with Optional<DirectoryEntryRef>.
+class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
+    : public Optional<DirectoryEntryRef> {
+public:
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
+      OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
+      const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
+  operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
+  operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
+
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {}
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
+      : Optional<DirectoryEntryRef>(Ref) {}
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional<DirectoryEntryRef> MaybeRef)
+      : Optional<DirectoryEntryRef>(MaybeRef) {}
+
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) {
+    Optional<DirectoryEntryRef>::operator=(None);
+    return *this;
+  }
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
+    Optional<DirectoryEntryRef>::operator=(Ref);
+    return *this;
+  }
+  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
+  operator=(Optional<DirectoryEntryRef> MaybeRef) {
+    Optional<DirectoryEntryRef>::operator=(MaybeRef);
+    return *this;
+  }
+
+  /// Degrade to 'const DirectoryEntry *' to allow  DirectoryEntry::LastRef and
+  /// DirectoryEntry::getName have been deleted, delete this class and replace
+  /// instances with Optional<DirectoryEntryRef>
+  operator const DirectoryEntry *() const {
+    return hasValue() ? &getValue().getDirEntry() : nullptr;
+  }
+};
+
+static_assert(std::is_trivially_copyable<
+                  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
+              "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
+              "trivially copyable");
+
+} // end namespace clang
+
 #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D90497: Mo... Duncan P. N. Exon Smith via Phabricator via cfe-commits
    • [PATCH] D9049... Duncan P. N. Exon Smith via Phabricator via cfe-commits
    • [PATCH] D9049... Duncan P. N. Exon Smith via Phabricator via cfe-commits
    • [PATCH] D9049... Duncan P. N. Exon Smith via Phabricator via cfe-commits

Reply via email to