diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -41,7 +41,7 @@ /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 26; +const unsigned VERSION_MAJOR = 27; /// AST file minor version number supported by this version of /// Clang. diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -2016,10 +2016,12 @@ Module *ShadowingModule = nullptr; if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { // We might see a (re)definition of a module that we already have a - // definition for in two cases: + // definition for in three cases: // - If we loaded one definition from an AST file and we've just found a // corresponding definition in a module map file, or - bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); + bool LoadedFromASTFile = Existing->IsFromModuleFile; + // - If we previously inferred this module from different module map file. + bool Inferred = Existing->IsInferred; // - If we're building a (preprocessed) module and we've just loaded the // module map file from which it was created. bool ParsedAsMainInput = @@ -2027,7 +2029,7 @@ Map.LangOpts.CurrentModule == ModuleName && SourceMgr.getDecomposedLoc(ModuleNameLoc).first != SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; - if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { + if (!ActiveModule && (LoadedFromASTFile || Inferred || ParsedAsMainInput)) { // Skip the module definition. skipUntil(MMToken::RBrace); if (Tok.is(MMToken::RBrace)) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5607,7 +5607,7 @@ break; case SUBMODULE_DEFINITION: { - if (Record.size() < 12) + if (Record.size() < 13) return llvm::createStringError(std::errc::illegal_byte_sequence, "malformed module definition"); @@ -5616,6 +5616,7 @@ SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]); SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]); Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++]; + SourceLocation DefinitionLoc = ReadSourceLocation(F, Record[Idx++]); bool IsFramework = Record[Idx++]; bool IsExplicit = Record[Idx++]; bool IsSystem = Record[Idx++]; @@ -5636,8 +5637,7 @@ ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit) .first; - // FIXME: set the definition loc for CurrentModule, or call - // ModMap.setInferredModuleAllowedBy() + // FIXME: Call ModMap.setInferredModuleAllowedBy() SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || @@ -5666,6 +5666,7 @@ } CurrentModule->Kind = Kind; + CurrentModule->DefinitionLoc = DefinitionLoc; CurrentModule->Signature = F.Signature; CurrentModule->IsFromModuleFile = true; CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -200,7 +200,9 @@ CB(F); FileID FID = SourceMgr.translateFile(F); SourceLocation Loc = SourceMgr.getIncludeLoc(FID); - while (Loc.isValid()) { + // The include location of inferred module maps can point into the header + // file that triggered the inferring. Cut off the walk if that's the case. + while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) { FID = SourceMgr.getFileID(Loc); CB(*SourceMgr.getFileEntryRefForID(FID)); Loc = SourceMgr.getIncludeLoc(FID); @@ -209,11 +211,18 @@ auto ProcessModuleOnce = [&](const Module *M) { for (const Module *Mod = M; Mod; Mod = Mod->Parent) - if (ProcessedModules.insert(Mod).second) + if (ProcessedModules.insert(Mod).second) { + auto Insert = [&](FileEntryRef F) { ModuleMaps.insert(F); }; + // The containing module map is affecting, because it's being pointed + // into by Module::DefinitionLoc. + if (auto ModuleMapFile = MM.getContainingModuleMapFile(Mod)) + ForIncludeChain(*ModuleMapFile, Insert); + // For inferred modules, the module map that allowed inferring is not in + // the include chain of the virtual containing module map file. It did + // affect the compilation, though. if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod)) - ForIncludeChain(*ModuleMapFile, [&](FileEntryRef F) { - ModuleMaps.insert(F); - }); + ForIncludeChain(*ModuleMapFile, Insert); + } }; for (const Module *CurrentModule : ModulesToProcess) { @@ -2687,6 +2696,7 @@ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem @@ -2787,12 +2797,16 @@ ParentID = SubmoduleIDs[Mod->Parent]; } + uint64_t DefinitionLoc = + SourceLocationEncoding::encode(getAdjustedLocation(Mod->DefinitionLoc)); + // Emit the definition of the block. { RecordData::value_type Record[] = {SUBMODULE_DEFINITION, ID, ParentID, (RecordData::value_type)Mod->Kind, + DefinitionLoc, Mod->IsFramework, Mod->IsExplicit, Mod->IsSystem,