diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -279,6 +279,8 @@ DiagnosticsEngine &getDiags() const { return Diags; } + std::vector &getFileInfo() const { return FileInfo; } + /// Interface for setting the file search paths. void SetSearchPaths(const std::vector &dirs, unsigned angledDirIdx, unsigned systemDirIdx, diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -475,7 +475,7 @@ createSignature(StringRef AllBytes, StringRef ASTBlockBytes); void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - bool Modules); + std::set &AffectingModuleMaps); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP); void WritePreprocessor(const Preprocessor &PP, bool IsModule); 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 @@ -149,6 +149,72 @@ namespace { +std::string ModuleMapFilePathForModule(const ModuleMap &Map, + Module *GivenModule) { + if (!GivenModule->PresumedModuleMapFile.empty()) { + return GivenModule->PresumedModuleMapFile; + } + auto *ModuleMapFile = Map.getModuleMapFileForUniquing(GivenModule); + if (!ModuleMapFile) { + return std::string(); + } + return std::string(ModuleMapFile->getName()); +} + +std::set GetAllModulemaps(const HeaderSearch &HS, + Module *RootModule) { + std::set ModuleMaps{}; + std::set ProcessedModules; + std::set ModulesToProcess{RootModule}; + + SmallVector FilesByUID; + HS.getFileMgr().GetUniqueIDMapping(FilesByUID); + + if (FilesByUID.size() > HS.header_file_size()) + FilesByUID.resize(HS.header_file_size()); + + for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { + const FileEntry *File = FilesByUID[UID]; + if (!File) + continue; + + const HeaderFileInfo *HFI = + HS.getExistingFileInfo(File, /*WantExternal*/false); + if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) + continue; + + const auto KH = HS.findModuleForHeader(File, /*AllowTextual*/true); + if (!KH.getModule()) + continue; + + ModulesToProcess.insert(KH.getModule()); + } + + while (!ModulesToProcess.empty()) { + auto CurrentModule = ModulesToProcess.begin(); + ProcessedModules.insert(*CurrentModule); + + const std::string CurrentModuleMapFile = + ModuleMapFilePathForModule(HS.getModuleMap(), *CurrentModule); + if (CurrentModuleMapFile.empty()) { + ModulesToProcess.erase(CurrentModule); + continue; + } + + ModuleMaps.insert(CurrentModuleMapFile); + + for (auto *ImportedModule : (*CurrentModule)->Imports) { + if (!ImportedModule || + ProcessedModules.find(ImportedModule) != ProcessedModules.end()) { + continue; + } + ModulesToProcess.insert(ImportedModule); + } + ModulesToProcess.erase(CurrentModule); + } + return ModuleMaps; +} + class ASTTypeWriter { ASTWriter &Writer; ASTWriter::RecordData Record; @@ -1396,9 +1462,16 @@ Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); } + std::set AffectingModulemaps; + if (WritingModule) { + AffectingModulemaps = GetAllModulemaps( + PP.getHeaderSearchInfo(), + WritingModule); + } + WriteInputFiles(Context.SourceMgr, PP.getHeaderSearchInfo().getHeaderSearchOpts(), - PP.getLangOpts().Modules); + AffectingModulemaps); Stream.ExitBlock(); } @@ -1418,7 +1491,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - bool Modules) { + std::set &AffectingModuleMaps) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); @@ -1458,6 +1531,15 @@ if (!Cache->OrigEntry) continue; + if (isModuleMap(File.getFileCharacteristic()) && + !isSystem(File.getFileCharacteristic()) && + !AffectingModuleMaps.empty() && + AffectingModuleMaps.find(std::string(Cache->OrigEntry->getName())) == + AffectingModuleMaps.end()) { + // Do not emit modulemaps that do not affect current module. + continue; + } + InputFileEntry Entry; Entry.File = Cache->OrigEntry; Entry.IsSystemFile = isSystem(File.getFileCharacteristic()); @@ -1971,11 +2053,15 @@ Record.push_back(SLoc->getOffset() - 2); if (SLoc->isFile()) { const SrcMgr::FileInfo &File = SLoc->getFile(); + const SrcMgr::ContentCache *Content = &File.getContentCache(); + if (Content->OrigEntry && InputFileIDs[Content->OrigEntry] == 0) { + // Do not emit files that were not listed as inputs. + continue; + } AddSourceLocation(File.getIncludeLoc(), Record); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding Record.push_back(File.hasLineDirectives()); - const SrcMgr::ContentCache *Content = &File.getContentCache(); bool EmitBlob = false; if (Content->OrigEntry) { assert(Content->OrigEntry == Content->ContentsEntry &&