Index: clang/include/clang/Basic/DiagnosticSerializationKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -74,6 +74,8 @@ "imported by %select{|module '%2' in }1'%0'">; def err_module_file_not_module : Error< "AST file '%0' was not built as a module">, DefaultFatal; +def err_module_file_missing_definition : Error< + "module file '%0' is missing the main module's definition">, DefaultFatal; def remark_module_import : Remark< "importing module '%0'%select{| into '%3'}2 from '%1'">, Index: clang/include/clang/Serialization/Module.h =================================================================== --- clang/include/clang/Serialization/Module.h +++ clang/include/clang/Serialization/Module.h @@ -159,6 +159,9 @@ /// Whether the PCH has a corresponding object file. bool PCHHasObjectFile = false; + /// Whether the main module has been read from the AST file. + bool DidReadMainModule = false; + /// The file entry for the module file. const FileEntry *File = nullptr; Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -4219,6 +4219,12 @@ if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) return removeModulesAndReturn(Result); + // The AST block should always have a definition for the main module. + if (F.isModule() && !F.DidReadMainModule) { + Error(diag::err_module_file_missing_definition, F.FileName); + return removeModulesAndReturn(Failure); + } + // Read the extension blocks. while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) { if (ASTReadResult Result = ReadExtensionBlock(F)) @@ -5494,6 +5500,7 @@ } } + F.DidReadMainModule = true; CurrentModule->setASTFile(F.File); CurrentModule->PresumedModuleMapFile = F.ModuleMapPath; }