diff --git a/clang/include/clang/Lex/ExternalPreprocessorSource.h b/clang/include/clang/Lex/ExternalPreprocessorSource.h --- a/clang/include/clang/Lex/ExternalPreprocessorSource.h +++ b/clang/include/clang/Lex/ExternalPreprocessorSource.h @@ -13,6 +13,8 @@ #ifndef LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H #define LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H +#include "clang/Lex/Preprocessor.h" + namespace clang { class IdentifierInfo; @@ -42,8 +44,7 @@ virtual Module *getModule(unsigned ModuleID) = 0; /// Return the files directly included in the given (sub)module. - virtual const llvm::DenseMap * - getIncludedFiles(Module *M) = 0; + virtual const Preprocessor::IncludeInfoMap *getIncludedFiles(Module *M) = 0; }; } diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -450,6 +450,11 @@ ElseLoc(ElseLoc) {} }; + struct IncludeInfo { + unsigned NumIncludes; + }; + using IncludeInfoMap = llvm::DenseMap; + private: friend class ASTReader; friend class MacroArgs; @@ -718,7 +723,6 @@ using MacroMap = llvm::DenseMap; struct SubmoduleState; - struct SubmoduleIncludeState; /// Information about a submodule that we're currently building. struct BuildingSubmoduleInfo { @@ -737,17 +741,12 @@ /// The number of pending module macro names when we started building this. unsigned OuterPendingModuleMacroNames; - /// The previous SubmoduleIncludeState. - SubmoduleIncludeState *OuterSubmoduleIncludeState; - BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, SubmoduleState *OuterSubmoduleState, - unsigned OuterPendingModuleMacroNames, - SubmoduleIncludeState *OuterSubmoduleIncludeState) + unsigned OuterPendingModuleMacroNames) : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), OuterSubmoduleState(OuterSubmoduleState), - OuterPendingModuleMacroNames(OuterPendingModuleMacroNames), - OuterSubmoduleIncludeState(OuterSubmoduleIncludeState) {} + OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} }; SmallVector BuildingSubmoduleStack; @@ -759,6 +758,8 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; + IncludeInfoMap IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -771,25 +772,8 @@ /// in a submodule. SubmoduleState *CurSubmoduleState; - /// Information about a (sub)module's preprocessor include state. - struct SubmoduleIncludeState { - /// For each included file, we track the number of includes. - llvm::DenseMap IncludedFiles; - - /// The set of modules that are visible within the submodule. - VisibleModuleSet VisibleModules; - }; /// The include state for each (sub)module. - std::map SubmoduleIncludeStates; - - /// The include state outside of any (sub)module. - SubmoduleIncludeState NullSubmoduleIncludeState; - - /// The current include state. - SubmoduleIncludeState *CurSubmoduleIncludeState; - - /// For each included file, we track the number of includes. - llvm::DenseMap IncludedFiles; + std::map IncludedFilesPerSubmodule; /// The set of known macros exported from modules. llvm::FoldingSet ModuleMacros; @@ -947,8 +931,7 @@ void updateOutOfDateIdentifier(IdentifierInfo &II) const; /// Get the external include information for the given (sub)module. - const llvm::DenseMap * - getExternalSubmoduleIncludes(Module *M) const; + const IncludeInfoMap *getExternalSubmoduleIncludes(Module *M) const; public: Preprocessor(std::shared_ptr PPOpts, @@ -1266,15 +1249,8 @@ /// Increment the include counter for a file transitively included file. void incrementTransitiveIncludeCount(const FileEntry *File, unsigned Count); - /// Get the include information outside of any (sub)module. - const llvm::DenseMap & - getNullSubmoduleIncludes() const { - return NullSubmoduleIncludeState.IncludedFiles; - } - /// Get the include information for the given local (sub)module. - const llvm::DenseMap * - getLocalSubmoduleIncludes(Module *M) const; + const IncludeInfoMap *getLocalSubmoduleIncludes(Module *M) const; /// Return the name of the macro defined before \p Loc that has /// spelling \p Tokens. If there are multiple macros with same spelling, 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 @@ -929,8 +929,7 @@ SmallVector ImportedModules; /// Mapping between a read (sub)module and the file include information. - llvm::DenseMap> - SubmoduleIncludedFiles; + llvm::DenseMap SubmoduleIncludedFiles; //@} /// The system include root to be used when loading the @@ -1385,8 +1384,8 @@ uint64_t getGlobalBitOffset(ModuleFile &M, uint64_t LocalOffset); /// Read the record containing files included in a (sub)module. - llvm::DenseMap - readIncludedFiles(ModuleFile &F, RecordData &Record); + Preprocessor::IncludeInfoMap readIncludedFiles(ModuleFile &F, + RecordData &Record); /// Returns the first preprocessed entity ID that begins or ends after /// \arg Loc. @@ -2108,8 +2107,7 @@ Module *getSubmodule(serialization::SubmoduleID GlobalID); /// Return the files directly included in the given (sub)module. - const llvm::DenseMap * - getIncludedFiles(Module *M) override; + const Preprocessor::IncludeInfoMap *getIncludedFiles(Module *M) override; /// Retrieve the module that corresponds to the given module ID. /// 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 @@ -19,6 +19,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" @@ -593,9 +594,8 @@ RecordDataImpl &Record); /// Emit included files information. - void - addIncludedFiles(const llvm::DenseMap &Files, - RecordDataImpl &Record); + void addIncludedFiles(const Preprocessor::IncludeInfoMap &Files, + RecordDataImpl &Record); /// Emit a source location. void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record); diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -687,11 +687,9 @@ bool ForPragma) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, ForPragma, CurSubmoduleState, - PendingModuleMacroNames.size(), CurSubmoduleIncludeState)); - - CurSubmoduleIncludeState = &SubmoduleIncludeStates[M]; + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); if (Callbacks) Callbacks->EnteredSubmodule(M, ImportLoc, ForPragma); @@ -735,16 +733,15 @@ } // Track that we entered this module. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, ForPragma, CurSubmoduleState, - PendingModuleMacroNames.size(), CurSubmoduleIncludeState)); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); if (Callbacks) Callbacks->EnteredSubmodule(M, ImportLoc, ForPragma); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; - CurSubmoduleIncludeState = &SubmoduleIncludeStates[M]; // This module is visible to itself. if (FirstTime) @@ -776,8 +773,6 @@ Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; - CurSubmoduleIncludeState = Info.OuterSubmoduleIncludeState; - if (!needModuleMacros() || (!getLangOpts().ModulesLocalVisibility && LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -91,8 +91,7 @@ // deferred to Preprocessor::Initialize(). Identifiers(IILookup), PragmaHandlers(new PragmaNamespace(StringRef())), TUKind(TUKind), SkipMainFilePreamble(0, true), - CurSubmoduleState(&NullSubmoduleState), - CurSubmoduleIncludeState(&NullSubmoduleIncludeState) { + CurSubmoduleState(&NullSubmoduleState) { OwnsHeaderSearch = OwnsHeaders; // Default to discarding comments. @@ -287,11 +286,12 @@ << " token paste (##) operations performed, " << NumFastTokenPaste << " on the fast path.\n"; + // FIXME: List information for all submodules. unsigned NumSingleIncludedFiles = 0, MaxNumIncludes = 0; - for (const auto &Include : IncludedFiles) { - if (MaxNumIncludes < Include.second) - MaxNumIncludes = Include.second; - NumSingleIncludedFiles += Include.second == 1; + for (const auto &IncludePair : CurSubmoduleState->IncludedFiles) { + if (MaxNumIncludes < IncludePair.second.NumIncludes) + MaxNumIncludes = IncludePair.second.NumIncludes; + NumSingleIncludedFiles += IncludePair.second.NumIncludes == 1; } llvm::errs() << NumSingleIncludedFiles << " files included exactly once.\n" << MaxNumIncludes << " max times a file is included.\n"; @@ -564,9 +564,6 @@ } } - if (Module *M = getCurrentModule()) - CurSubmoduleIncludeState = &SubmoduleIncludeStates[M]; - // Preprocess Predefines to populate the initial preprocessor state. std::unique_ptr SB = llvm::MemoryBuffer::getMemBufferCopy(Predefines, ""); @@ -1320,7 +1317,16 @@ void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc) { CurSubmoduleState->VisibleModules.setVisible( - M, Loc, [](Module *) {}, + M, Loc, + [&](Module *M) { + const IncludeInfoMap *Includes = getLocalSubmoduleIncludes(M); + if (!Includes) + Includes = getExternalSubmoduleIncludes(M); + if (Includes) + for (const auto &E : *Includes) + incrementTransitiveIncludeCount(E.getFirst(), + E.getSecond().NumIncludes); + }, [&](ArrayRef Path, Module *Conflict, StringRef Message) { // FIXME: Include the path in the diagnostic. // FIXME: Include the import location for the conflicting module. @@ -1330,18 +1336,6 @@ << Message; }); - CurSubmoduleIncludeState->VisibleModules.setVisible( - M, Loc, - [&](Module *M) { - const auto *Includes = getLocalSubmoduleIncludes(M); - if (!Includes) - Includes = getExternalSubmoduleIncludes(M); - if (Includes) - for (const auto &E : *Includes) - incrementTransitiveIncludeCount(E.getFirst(), E.getSecond()); - }, - [](ArrayRef, Module *, StringRef) {}); - // Add this module to the imports list of the currently-built submodule. if (!BuildingSubmoduleStack.empty() && M != BuildingSubmoduleStack.back().M) BuildingSubmoduleStack.back().M->Imports.insert(M); @@ -1495,17 +1489,17 @@ } bool Preprocessor::includedAtLeastOnce(const FileEntry *File) const { - auto It = IncludedFiles.find(File); - if (It == IncludedFiles.end()) + auto It = CurSubmoduleState->IncludedFiles.find(File); + if (It == CurSubmoduleState->IncludedFiles.end()) return false; - return It->second >= 1; + return It->second.NumIncludes >= 1; } bool Preprocessor::firstTimeLexingFile(const FileEntry *File) const { - auto It = IncludedFiles.find(File); - if (It == IncludedFiles.end()) + auto It = CurSubmoduleState->IncludedFiles.find(File); + if (It == CurSubmoduleState->IncludedFiles.end()) return false; - return It->second == 1; + return It->second.NumIncludes == 1; } void Preprocessor::incrementTransitiveIncludeCount(const FileEntry *File, @@ -1513,23 +1507,29 @@ // Compared to `incrementIncludeCount`, we're not incrementing the count in // CurSubmoduleIncludeState`. This is to ensure it always only contains // **locally** included files and not transitively included ones. - IncludedFiles[File] += Count; + CurSubmoduleState->IncludedFiles[File].NumIncludes += Count; } void Preprocessor::incrementIncludeCount(const FileEntry *File) { - CurSubmoduleIncludeState->IncludedFiles[File] += 1; - IncludedFiles[File] += 1; + Module *CurrentSubmodule = nullptr; + if (!BuildingSubmoduleStack.empty()) + CurrentSubmodule = BuildingSubmoduleStack.back().M; + else + CurrentSubmodule = getCurrentModule(); + if (CurrentSubmodule) + IncludedFilesPerSubmodule[CurrentSubmodule][File].NumIncludes += 1; + CurSubmoduleState->IncludedFiles[File].NumIncludes += 1; } -const llvm::DenseMap * +const Preprocessor::IncludeInfoMap * Preprocessor::getLocalSubmoduleIncludes(Module *M) const { - auto It = SubmoduleIncludeStates.find(M); - if (It != SubmoduleIncludeStates.end()) - return &It->second.IncludedFiles; + auto It = IncludedFilesPerSubmodule.find(M); + if (It != IncludedFilesPerSubmodule.end()) + return &It->second; return nullptr; } -const llvm::DenseMap * +const Preprocessor::IncludeInfoMap * Preprocessor::getExternalSubmoduleIncludes(Module *M) const { if (ExternalSource) return ExternalSource->getIncludedFiles(M); 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 @@ -3702,7 +3702,8 @@ break; for (const auto &E : readIncludedFiles(F, Record)) - PP.incrementTransitiveIncludeCount(E.getFirst(), E.getSecond()); + PP.incrementTransitiveIncludeCount(E.getFirst(), + E.getSecond().NumIncludes); break; } @@ -8605,8 +8606,8 @@ return LocalID + I->second; } -llvm::DenseMap -ASTReader::readIncludedFiles(ModuleFile &F, RecordData &Record) { +Preprocessor::IncludeInfoMap ASTReader::readIncludedFiles(ModuleFile &F, + RecordData &Record) { unsigned Idx = 0; unsigned TotalCount = Record[Idx++]; unsigned IncludedOnceCount = Record[Idx++]; @@ -8617,25 +8618,25 @@ return FileMgr.getOptionalFileRef(InputFileInfo.Filename); }; - llvm::DenseMap Result; + Preprocessor::IncludeInfoMap Result; for (unsigned I = 0; I < IncludedOnceCount; ++I) if (const FileEntry *File = ReadFile()) - Result.insert({File, 1}); + Result.insert({File, {1}}); for (unsigned I = 0; I < TotalCount - IncludedOnceCount; ++I) if (const FileEntry *File = ReadFile()) - Result.insert({File, 2}); // squash "more than one" include into exactly 2 + Result.insert( + {File, {2}}); // squash "more than one" include into exactly 2 return Result; } -const llvm::DenseMap * -ASTReader::getIncludedFiles(Module *M) { +const Preprocessor::IncludeInfoMap *ASTReader::getIncludedFiles(Module *M) { ModuleFile *F = getModuleManager().lookup(M->getASTFile()); if (!F) return nullptr; - auto ResultIt = SubmoduleIncludedFiles.insert( - {M, llvm::DenseMap{}}); - auto &Result = ResultIt.first->second; + auto ResultIt = + SubmoduleIncludedFiles.insert({M, Preprocessor::IncludeInfoMap{}}); + Preprocessor::IncludeInfoMap &Result = ResultIt.first->second; if (!ResultIt.second) return &Result; 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 @@ -57,7 +57,6 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/Token.h" #include "clang/Sema/IdentifierResolver.h" @@ -2170,16 +2169,15 @@ return false; } -void ASTWriter::addIncludedFiles( - const llvm::DenseMap &Files, - RecordDataImpl &Record) { +void ASTWriter::addIncludedFiles(const Preprocessor::IncludeInfoMap &Files, + RecordDataImpl &Record) { // Map the FileEntry map into an input file ID vector. llvm::SmallVector> FileIDs; for (const auto &E : Files) { auto InputFileIt = InputFileIDs.find(E.first); assert(InputFileIt != InputFileIDs.end() && "Included file is an known input file"); - FileIDs.emplace_back(InputFileIt->second, E.second); + FileIDs.emplace_back(InputFileIt->second, E.second.NumIncludes); } // Ensure the order is stable. @@ -2414,10 +2412,6 @@ MacroOffsetsBase - ASTBlockStartOffset}; Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets)); } - - addIncludedFiles(PP.getNullSubmoduleIncludes(), Record); - Stream.EmitRecord(PP_NUM_INCLUDES, Record); - Record.clear(); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, @@ -2814,7 +2808,8 @@ Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule); } - if (const auto *Includes = PP->getLocalSubmoduleIncludes(Mod)) { + if (const Preprocessor::IncludeInfoMap *Includes = + PP->getLocalSubmoduleIncludes(Mod)) { RecordData Record; addIncludedFiles(*Includes, Record); Stream.EmitRecord(SUBMODULE_NUM_INCLUDES, Record);