summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2019-08-29 23:14:08 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2019-08-29 23:14:08 +0000
commitd6beacf5d7933083d3a3102102d3d8b379288aa5 (patch)
treec9958cd46fa7727b359fda05edd396594a9abd1d
parentb27d7164069510c464647b838b41327bd5257d4d (diff)
downloadclang-d6beacf5d7933083d3a3102102d3d8b379288aa5.tar.gz
[Modules] Make ReadModuleMapFileBlock errors reliable
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
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td4
-rw-r--r--lib/Serialization/ASTReader.cpp16
2 files changed, 11 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 43ba19b585..0461d2f429 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -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 "
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 6a18af8a08..aaa59fcf50 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -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;
}