diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1247,18 +1247,8 @@ /// Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); - struct InputFileInfo { - std::string Filename; - uint64_t ContentHash; - off_t StoredSize; - time_t StoredTime; - bool Overridden; - bool Transient; - bool TopLevelModuleMap; - }; - - /// Reads the stored information about an input file. - InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID); + /// Retrieve the stored information about an input file. + serialization::InputFileInfo getInputFileInfo(ModuleFile &F, unsigned ID); /// Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -59,6 +59,17 @@ MK_PrebuiltModule }; +/// The input file info that has been loaded from an AST file. +struct InputFileInfo { + std::string Filename; + uint64_t ContentHash; + off_t StoredSize; + time_t StoredTime; + bool Overridden; + bool Transient; + bool TopLevelModuleMap; +}; + /// The input file that has been loaded from this AST file, along with /// bools indicating whether this was an overridden buffer or if it was /// out-of-date or not-found. @@ -235,6 +246,9 @@ /// The input files that have been loaded from this AST file. std::vector InputFilesLoaded; + /// The input file infos that have been loaded from this AST file. + std::vector InputFileInfosLoaded; + // All user input files reside at the index range [0, NumUserInputFiles), and // system input files reside at [NumUserInputFiles, InputFilesLoaded.size()). unsigned NumUserInputFiles = 0; 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 @@ -2266,8 +2266,15 @@ return false; } -ASTReader::InputFileInfo -ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) { +InputFileInfo ASTReader::getInputFileInfo(ModuleFile &F, unsigned ID) { + // If this ID is bogus, just return an empty input file. + if (ID == 0 || ID > F.InputFileInfosLoaded.size()) + return InputFileInfo(); + + // If we've already loaded this input file, return it. + if (!F.InputFileInfosLoaded[ID - 1].Filename.empty()) + return F.InputFileInfosLoaded[ID - 1]; + // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); @@ -2320,6 +2327,9 @@ } R.ContentHash = (static_cast(Record[1]) << 32) | static_cast(Record[0]); + + // Note that we've loaded this input file info. + F.InputFileInfosLoaded[ID - 1] = R; return R; } @@ -2344,7 +2354,7 @@ consumeError(std::move(Err)); } - InputFileInfo FI = readInputFileInfo(F, ID); + InputFileInfo FI = getInputFileInfo(F, ID); off_t StoredSize = FI.StoredSize; time_t StoredTime = FI.StoredTime; bool Overridden = FI.Overridden; @@ -2691,7 +2701,7 @@ : NumUserInputs; for (unsigned I = 0; I < N; ++I) { bool IsSystem = I >= NumUserInputs; - InputFileInfo FI = readInputFileInfo(F, I+1); + InputFileInfo FI = getInputFileInfo(F, I + 1); Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden, F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule); @@ -2968,6 +2978,7 @@ F.InputFileOffsets = (const llvm::support::unaligned_uint64_t *)Blob.data(); F.InputFilesLoaded.resize(NumInputs); + F.InputFileInfosLoaded.resize(NumInputs); F.NumUserInputFiles = NumUserInputs; break; } @@ -2983,7 +2994,7 @@ for (unsigned I = 0; I < FileCount; ++I) { size_t ID = endian::readNext(D); - InputFileInfo IFI = readInputFileInfo(F, ID); + InputFileInfo IFI = getInputFileInfo(F, ID); if (llvm::ErrorOr File = PP.getFileManager().getFile(IFI.Filename)) PP.getIncludedFiles().insert(*File); @@ -9217,9 +9228,8 @@ llvm::function_ref Visitor) { unsigned NumInputs = MF.InputFilesLoaded.size(); for (unsigned I = 0; I < NumInputs; ++I) { - InputFileInfo IFI = readInputFileInfo(MF, I + 1); + InputFileInfo IFI = getInputFileInfo(MF, I + 1); if (IFI.TopLevelModuleMap) - // FIXME: This unnecessarily re-reads the InputFileInfo. if (auto FE = getInputFile(MF, I + 1).getFile()) Visitor(*FE); }