]> granicus.if.org Git - clang/commitdiff
[Modules] Make ReadModuleMapFileBlock errors reliable
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Thu, 29 Aug 2019 23:14:08 +0000 (23:14 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Thu, 29 Aug 2019 23:14:08 +0000 (23:14 +0000)
This prevents a crash when an error should be emitted instead.

During implicit module builds, there are cases where ReadASTCore is called with
ImportedBy set to nullptr, which breaks expectations in ReadModuleMapFileBlock,
leading to crashes.

Fix this by improving ReadModuleMapFileBlock to handle ImportedBy correctly.
This only happens non deterministically in the wild, when the underlying file
system changes while concurrent compiler invocations use implicit modules,
forcing rebuilds which see an inconsistent filesystem state. That said, there's
no much to do w.r.t. writing tests here.

rdar://problem/48828801

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370422 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSerializationKinds.td
lib/Serialization/ASTReader.cpp

index 43ba19b5853e2643650f47fe41dab39eff71779e..0461d2f429a7be00a3c639b5588b1861d9072a9d 100644 (file)
@@ -77,13 +77,13 @@ def remark_module_import : Remark<
   InGroup<ModuleImport>;
 
 def err_imported_module_not_found : Error<
-    "module '%0' in AST file '%1' (imported by AST file '%2') "
+    "module '%0' in AST file '%1' %select{(imported by AST file '%2') |}4"
     "is not defined in any loaded module map file; "
     "maybe you need to load '%3'?">, DefaultFatal;
 def note_imported_by_pch_module_not_found : Note<
     "consider adding '%0' to the header search path">;
 def err_imported_module_modmap_changed : Error<
-    "module '%0' imported by AST file '%1' found in a different module map file"
+    "module '%0' %select{in|imported by}4 AST file '%1' found in a different module map file"
     " (%2) than when the importing AST file was built (%3)">, DefaultFatal;
 def err_imported_module_relocated : Error<
     "module '%0' was built in directory '%1' but now resides in "
index 6a18af8a082236e8244b24f80b97cf44244f25ea..aaa59fcf506219962222d206647d9c933d14814c 100644 (file)
@@ -3823,7 +3823,6 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
     const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
     // Don't emit module relocation error if we have -fno-validate-pch
     if (!PP.getPreprocessorOpts().DisablePCHValidation && !ModMap) {
-      assert(ImportedBy && "top-level import should be verified");
       if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
         if (auto *ASTFE = M ? M->getASTFile() : nullptr) {
           // This module was defined by an imported (explicit) module.
@@ -3832,12 +3831,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
         } else {
           // This module was built with a different module map.
           Diag(diag::err_imported_module_not_found)
-              << F.ModuleName << F.FileName << ImportedBy->FileName
-              << F.ModuleMapPath;
+              << F.ModuleName << F.FileName
+              << (ImportedBy ? ImportedBy->FileName : "") << F.ModuleMapPath
+              << !ImportedBy;
           // In case it was imported by a PCH, there's a chance the user is
           // just missing to include the search path to the directory containing
           // the modulemap.
-          if (ImportedBy->Kind == MK_PCH)
+          if (ImportedBy && ImportedBy->Kind == MK_PCH)
             Diag(diag::note_imported_by_pch_module_not_found)
                 << llvm::sys::path::parent_path(F.ModuleMapPath);
         }
@@ -3851,11 +3851,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
     auto StoredModMap = FileMgr.getFile(F.ModuleMapPath);
     if (!StoredModMap || *StoredModMap != ModMap) {
       assert(ModMap && "found module is missing module map file");
-      assert(ImportedBy && "top-level import should be verified");
+      assert((ImportedBy || F.Kind == MK_ImplicitModule) &&
+             "top-level import should be verified");
+      bool NotImported = F.Kind == MK_ImplicitModule && !ImportedBy;
       if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
         Diag(diag::err_imported_module_modmap_changed)
-          << F.ModuleName << ImportedBy->FileName
-          << ModMap->getName() << F.ModuleMapPath;
+            << F.ModuleName << (NotImported ? F.FileName : ImportedBy->FileName)
+            << ModMap->getName() << F.ModuleMapPath << NotImported;
       return OutOfDate;
     }