oontvoo updated this revision to Diff 252203.
oontvoo added a comment.

(hopefully) Final revision ... running out of idea for edit comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D75951

Files:
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Serialization/ASTBitCodes.h
  clang/include/clang/Serialization/ASTReader.h
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp

Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -1599,6 +1599,8 @@
       const HeaderFileInfo &HFI;
       ArrayRef<ModuleMap::KnownHeader> KnownHeaders;
       UnresolvedModule Unresolved;
+      uint32_t UID;
+      uint32_t FileIndex;
     };
     using data_type_ref = const data_type &;
 
@@ -1676,6 +1678,10 @@
       }
       LE.write<uint32_t>(Offset);
 
+      // Write this file UID and its index into the array where it was written.
+      LE.write<uint32_t>(Data.UID);
+      LE.write<uint32_t>(Data.FileIndex);
+
       auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {
         if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {
           uint32_t Value = (ModID << 2) | (unsigned)Role;
@@ -1800,7 +1806,8 @@
       Filename, File->getSize(), getTimestampForOutput(File)
     };
     HeaderFileInfoTrait::data_type Data = {
-      *HFI, HS.getModuleMap().findAllModulesForHeader(File), {}
+      *HFI, HS.getModuleMap().findAllModulesForHeader(File), {},
+      File->getUID(), UID,
     };
     Generator.insert(Key, Data, GeneratorTrait);
     ++NumHeaderSearchEntries;
@@ -2634,6 +2641,18 @@
       Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
     }
 
+    // Emit the imported header's UIDs.
+    {
+      auto it = PP->Submodules.find(Mod);
+      if (it != PP->Submodules.end() && !it->second.IncludedFiles.empty() ) {
+        RecordData Record;
+        for (auto FileUID : it->second.IncludedFiles) {
+          Record.push_back(FileUID);
+        }
+        Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record);
+      }
+    }
+
     // Emit the exports.
     if (!Mod->Exports.empty()) {
       RecordData Record;
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -1898,6 +1898,13 @@
     HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
   }
 
+  // Read the file old UID
+  {
+    HFI.UID = endian::readNext<uint32_t, little, unaligned>(d);
+    //TODO: seems the index is not needed
+    const uint32_t OldIndex = endian::readNext<uint32_t, little, unaligned>(d);
+  }
+
   assert((End - d) % 4 == 0 &&
          "Wrong data length in HeaderFileInfo deserialization");
   while (d != End) {
@@ -9271,6 +9278,37 @@
   for (auto *ND : PendingMergedDefinitionsToDeduplicate)
     getContext().deduplicateMergedDefinitonsFor(ND);
   PendingMergedDefinitionsToDeduplicate.clear();
+
+  // Fix up the HeaderSearchInfo UIDs.
+  if (!PendingImportedHeaders.empty()){
+    std::map<unsigned, unsigned> OldToNewUID;
+
+    // These HFIs were deserialized and assigned their "old"
+    // UID.
+    // We need to update them and populate the OldToNewUID map
+    // for use next.
+    HeaderSearch& HS = PP->getHeaderSearchInfo();
+    for (unsigned NewUID = 0; NewUID < HS.FileInfo.size(); ++NewUID) {
+      OldToNewUID[HS.FileInfo[NewUID].UID] = NewUID;
+      HS.FileInfo[NewUID].UID = NewUID;
+    }
+
+    auto& Iter = PendingImportedHeaders.begin();
+    for (unsigned I = 0; I < PendingImportedHeaders.size(); ++I){
+      ModuleFile* ModFile = Iter[I].first;
+      auto& HeaderUIDs = Iter[I].second;
+      Module *M = HS.lookupModule(ModFile->ModuleName);
+
+      SubmoduleState& SubState = PP.Submodulels[M];
+      for (unsigned OldUid : HeaderUIDs) {
+        auto NewUIDIt = OldToNewUID.find(OldUid);
+        assert(NewUIDIt != OldToNewUID.end());
+
+        SubState.IncludedFiles.insert(NewUIDIt->second);
+      }
+    }
+    PendingImportedHeaders.clear();
+  }
 }
 
 void ASTReader::diagnoseOdrViolations() {
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1253,60 +1253,21 @@
   // Get information about this file.
   HeaderFileInfo &FileInfo = getFileInfo(File);
 
-  // FIXME: this is a workaround for the lack of proper modules-aware support
-  // for #import / #pragma once
-  auto TryEnterImported = [&]() -> bool {
-    if (!ModulesEnabled)
-      return false;
-    // Ensure FileInfo bits are up to date.
-    ModMap.resolveHeaderDirectives(File);
-    // Modules with builtins are special; multiple modules use builtins as
-    // modular headers, example:
-    //
-    //    module stddef { header "stddef.h" export * }
-    //
-    // After module map parsing, this expands to:
-    //
-    //    module stddef {
-    //      header "/path_to_builtin_dirs/stddef.h"
-    //      textual "stddef.h"
-    //    }
-    //
-    // It's common that libc++ and system modules will both define such
-    // submodules. Make sure cached results for a builtin header won't
-    // prevent other builtin modules to potentially enter the builtin header.
-    // Note that builtins are header guarded and the decision to actually
-    // enter them is postponed to the controlling macros logic below.
-    bool TryEnterHdr = false;
-    if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader)
-      TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() &&
-                    ModuleMap::isBuiltinHeader(
-                        llvm::sys::path::filename(File->getName()));
-
-    // Textual headers can be #imported from different modules. Since ObjC
-    // headers find in the wild might rely only on #import and do not contain
-    // controlling macros, be conservative and only try to enter textual headers
-    // if such macro is present.
-    if (!FileInfo.isModuleHeader &&
-        FileInfo.getControllingMacro(ExternalLookup))
-      TryEnterHdr = true;
-    return TryEnterHdr;
-  };
+  assert(FileInfo.UID == File->getUID());
 
   // If this is a #import directive, check that we have not already imported
   // this header.
   if (isImport) {
     // If this has already been imported, don't import it again.
     FileInfo.isImport = true;
+  }
 
-    // Has this already been #import'ed or #include'd?
-    if (FileInfo.NumIncludes && !TryEnterImported())
-      return false;
-  } else {
-    // Otherwise, if this is a #include of a file that was previously #import'd
-    // or if this is the second #include of a #pragma once file, ignore it.
-    if (FileInfo.isImport && !TryEnterImported())
-      return false;
+  if (FileInfo.isPragmaOnce || FileInfo.isImport) {
+    if (PP.isIncludeVisible(FileInfo.UID))return false;
+    else {
+      // Mark as 'included'.
+      PP.setIncludeVisible(FileInfo.UID);
+    }
   }
 
   // Next, check to see if the file is wrapped with #ifndef guards.  If so, and
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -736,6 +736,12 @@
   /// IDs have not yet been deserialized to the global IDs of those macros.
   PendingMacroIDsMap PendingMacroIDs;
 
+  /// Mapping from ModuleFile to a list of its imported headers' (old) UID.
+  /// These UIDs are yet to be mapped to their corresponding HeaderFileInfo
+  using PendingImportedHeadersMap =
+      llvm::MapVector<ModuleFile*, SmallVector<unsigned, 8>>;
+  PendingImportedHeadersMap PendingImportedHeaders;
+
   using GlobalPreprocessedEntityMapType =
       ContinuousRangeMap<unsigned, ModuleFile *, 4>;
 
@@ -2198,6 +2204,11 @@
   void addPendingMacro(IdentifierInfo *II, ModuleFile *M,
                        uint64_t MacroDirectivesOffset);
 
+  /// Add a HeaderSearch to the set of pending objects to be looked at later.
+  void addPendingHeaderSearch(HeaderSearch* HS) {
+    PendingHeaderSearch.insert(HS);
+  }
+
   /// Read the set of macros defined by this external macro source.
   void ReadDefinedMacros() override;
 
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -781,6 +781,9 @@
       /// Specifies the name of the module that will eventually
       /// re-export the entities in this module.
       SUBMODULE_EXPORT_AS = 17,
+
+      // Specifies the headers' UID imported by this submodule.
+      SUBMODULE_IMPORTED_HEADERS = 18,
     };
 
     /// Record types used within a comments block.
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -51,6 +51,7 @@
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -128,6 +129,8 @@
 class Preprocessor {
   friend class VAOptDefinitionContext;
   friend class VariadicMacroScopeGuard;
+  friend class ASTWriter;
+  friend class ASTReader;
 
   llvm::unique_function<void(const clang::Token &)> OnToken;
   std::shared_ptr<PreprocessorOptions> PPOpts;
@@ -743,6 +746,9 @@
     /// The set of modules that are visible within the submodule.
     VisibleModuleSet VisibleModules;
 
+    /// The set of UIDs from the included header for the submodule.
+    std::set<unsigned> IncludedFiles;
+
     // FIXME: CounterValue?
     // FIXME: PragmaPushMacroInfo?
   };
@@ -1038,6 +1044,15 @@
     OnToken = std::move(F);
   }
 
+  void setIncludeVisible(const unsigned UID) {
+    CurSubmoduleState->IncludedFiles.insert(UID);
+  }
+
+  bool isIncludeVisible(const unsigned UID) {
+    return CurSubmoduleState->IncludedFiles.find(UID) !=
+           CurSubmoduleState->IncludedFiles.end();
+  }
+
   bool isMacroDefined(StringRef Id) {
     return isMacroDefined(&Identifiers.get(Id));
   }
Index: clang/include/clang/Lex/HeaderSearch.h
===================================================================
--- clang/include/clang/Lex/HeaderSearch.h
+++ clang/include/clang/Lex/HeaderSearch.h
@@ -110,10 +110,15 @@
   /// of the framework.
   StringRef Framework;
 
+  /// The file UID used during [de]serialization.
+  unsigned UID = 0;
+
+  bool FinishedLoadingImporters;
+
   HeaderFileInfo()
       : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
         External(false), isModuleHeader(false), isCompilingModuleHeader(false),
-        Resolved(false), IndexHeaderMapHeader(false), IsValid(false)  {}
+        Resolved(false), IndexHeaderMapHeader(false), IsValid(false), FinishedLoadingImporters(false)  {}
 
   /// Retrieve the controlling macro for this header file, if
   /// any.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to