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,13 @@ if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) return removeModulesAndReturn(Result); + if (F.isModule() && !F.DidReadMainModule) { + // The AST block is malformed if it does not contain a definition for the + // main module. + Error("missing main SUBMODULE_DEFINITION in AST file"); + return removeModulesAndReturn(Failure); + } + // Read the extension blocks. while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) { if (ASTReadResult Result = ReadExtensionBlock(F)) @@ -5494,6 +5501,7 @@ } } + F.DidReadMainModule = true; CurrentModule->setASTFile(F.File); CurrentModule->PresumedModuleMapFile = F.ModuleMapPath; }