From: Alex Lorenz Date: Wed, 19 Jun 2019 17:07:36 +0000 (+0000) Subject: Unify DependencyFileGenerator class and DependencyCollector interface (NFCI) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4df2fbbebb653f12f61ed3537ec2c99509d43a5b;p=clang Unify DependencyFileGenerator class and DependencyCollector interface (NFCI) Make DependencyFileGenerator a DependencyCollector as it was intended when DependencyCollector was introduced. The missing PPCallbacks overrides are added to the DependencyCollector as well. This change will allow clang-scan-deps to access the produced dependencies without writing them out to .d files to disk, so that it will be able collate them and report them to the user. Differential Revision: https://reviews.llvm.org/D63290 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@363840 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 2eb1349f49..eb49c53ff4 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -124,9 +124,6 @@ class CompilerInstance : public ModuleLoader { /// The module provider. std::shared_ptr ThePCHContainerOperations; - /// The dependency file generator. - std::unique_ptr TheDependencyFileGenerator; - std::vector> DependencyCollectors; /// The set of top-level modules that has already been loaded, @@ -661,7 +658,6 @@ public: InMemoryModuleCache &ModuleCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, ArrayRef> Extensions, - DependencyFileGenerator *DependencyFile, ArrayRef> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex); diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 124d4a9933..951d51bbc1 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -15,6 +15,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" +#include "clang/Frontend/DependencyOutputOptions.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" @@ -46,7 +47,6 @@ namespace clang { class ASTReader; class CompilerInstance; class CompilerInvocation; -class DependencyOutputOptions; class DiagnosticsEngine; class ExternalSemaSource; class FrontendOptions; @@ -77,8 +77,7 @@ void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, /// An interface for collecting the dependencies of a compilation. Users should /// use \c attachToPreprocessor and \c attachToASTReader to get all of the /// dependencies. -/// FIXME: Migrate DependencyFileGen and DependencyGraphGen to use this -/// interface. +/// FIXME: Migrate DependencyGraphGen to use this interface. class DependencyCollector { public: virtual ~DependencyCollector(); @@ -95,7 +94,7 @@ public: bool IsSystem, bool IsModuleFile, bool IsMissing); /// Called when the end of the main file is reached. - virtual void finishedMainFile() {} + virtual void finishedMainFile(DiagnosticsEngine &Diags) {} /// Return true if system files should be passed to sawDependency(). virtual bool needSystemDependencies() { return false; } @@ -106,25 +105,45 @@ public: void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing); +protected: + /// Return true if the filename was added to the list of dependencies, false + /// otherwise. + bool addDependency(StringRef Filename); + private: llvm::StringSet<> Seen; std::vector Dependencies; }; -/// Builds a depdenency file when attached to a Preprocessor (for includes) and +/// Builds a dependency file when attached to a Preprocessor (for includes) and /// ASTReader (for module imports), and writes it out at the end of processing /// a source file. Users should attach to the ast reader whenever a module is /// loaded. -class DependencyFileGenerator { - void *Impl; // Opaque implementation +class DependencyFileGenerator : public DependencyCollector { +public: + DependencyFileGenerator(const DependencyOutputOptions &Opts); - DependencyFileGenerator(void *Impl); + void attachToPreprocessor(Preprocessor &PP) override; -public: - static DependencyFileGenerator *CreateAndAttachToPreprocessor( - Preprocessor &PP, const DependencyOutputOptions &Opts); + void finishedMainFile(DiagnosticsEngine &Diags) override; - void AttachToASTReader(ASTReader &R); + bool needSystemDependencies() final override { return IncludeSystemHeaders; } + + bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, + bool IsModuleFile, bool IsMissing) final override; + +private: + void outputDependencyFile(DiagnosticsEngine &Diags); + + std::string OutputFile; + std::vector Targets; + bool IncludeSystemHeaders; + bool PhonyTarget; + bool AddMissingHeaderDeps; + bool SeenMissingHeader; + bool IncludeModuleFiles; + DependencyOutputFormat OutputFormat; + unsigned InputFileIndex; }; /// Collects the dependencies for imported modules into a directory. Users diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index fd33b85b31..9cbc9ed1f7 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -415,8 +415,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { // Handle generating dependencies, if requested. const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); if (!DepOpts.OutputFile.empty()) - TheDependencyFileGenerator.reset( - DependencyFileGenerator::CreateAndAttachToPreprocessor(*PP, DepOpts)); + addDependencyCollector(std::make_shared(DepOpts)); if (!DepOpts.DOTOutputFile.empty()) AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, getHeaderSearchOpts().Sysroot); @@ -490,9 +489,9 @@ void CompilerInstance::createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(), getASTContext(), getPCHContainerReader(), - getFrontendOpts().ModuleFileExtensions, TheDependencyFileGenerator.get(), - DependencyCollectors, DeserializationListener, OwnDeserializationListener, - Preamble, getFrontendOpts().UseGlobalModuleIndex); + getFrontendOpts().ModuleFileExtensions, DependencyCollectors, + DeserializationListener, OwnDeserializationListener, Preamble, + getFrontendOpts().UseGlobalModuleIndex); } IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( @@ -501,7 +500,6 @@ IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( InMemoryModuleCache &ModuleCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, ArrayRef> Extensions, - DependencyFileGenerator *DependencyFile, ArrayRef> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex) { @@ -521,8 +519,6 @@ IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( static_cast(DeserializationListener), /*TakeOwnership=*/OwnDeserializationListener); - if (DependencyFile) - DependencyFile->AttachToASTReader(*Reader); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*Reader); @@ -1492,8 +1488,6 @@ void CompilerInstance::createModuleManager() { if (hasASTConsumer()) ModuleManager->StartTranslationUnit(&getASTConsumer()); - if (TheDependencyFileGenerator) - TheDependencyFileGenerator->AttachToASTReader(*ModuleManager); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*ModuleManager); } diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 363aff76f0..b52e25bb0e 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -32,8 +32,10 @@ namespace { struct DepCollectorPPCallbacks : public PPCallbacks { DependencyCollector &DepCollector; SourceManager &SM; - DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM) - : DepCollector(L), SM(SM) { } + DiagnosticsEngine &Diags; + DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM, + DiagnosticsEngine &Diags) + : DepCollector(L), SM(SM), Diags(Diags) {} void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -57,6 +59,16 @@ struct DepCollectorPPCallbacks : public PPCallbacks { /*IsModuleFile*/false, /*IsMissing*/false); } + void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) override { + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(SkippedFile.getName()); + DepCollector.maybeAddDependency(Filename, /*FromModule=*/false, + /*IsSystem=*/isSystem(FileType), + /*IsModuleFile=*/false, + /*IsMissing=*/false); + } + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, @@ -70,9 +82,20 @@ struct DepCollectorPPCallbacks : public PPCallbacks { // Files that actually exist are handled by FileChanged. } - void EndOfMainFile() override { - DepCollector.finishedMainFile(); + void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled, + const FileEntry *File, + SrcMgr::CharacteristicKind FileType) override { + if (!File) + return; + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(File->getName()); + DepCollector.maybeAddDependency(Filename, /*FromModule=*/false, + /*IsSystem=*/isSystem(FileType), + /*IsModuleFile=*/false, + /*IsMissing=*/false); } + + void EndOfMainFile() override { DepCollector.finishedMainFile(Diags); } }; struct DepCollectorMMCallbacks : public ModuleMapCallbacks { @@ -117,9 +140,16 @@ struct DepCollectorASTListener : public ASTReaderListener { void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) { - if (Seen.insert(Filename).second && - sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) + if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) + addDependency(Filename); +} + +bool DependencyCollector::addDependency(StringRef Filename) { + if (Seen.insert(Filename).second) { Dependencies.push_back(Filename); + return true; + } + return false; } static bool isSpecialFilename(StringRef Filename) { @@ -138,8 +168,8 @@ bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule, DependencyCollector::~DependencyCollector() { } void DependencyCollector::attachToPreprocessor(Preprocessor &PP) { - PP.addPPCallbacks( - llvm::make_unique(*this, PP.getSourceManager())); + PP.addPPCallbacks(llvm::make_unique( + *this, PP.getSourceManager(), PP.getDiagnostics())); PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( llvm::make_unique(*this)); } @@ -147,206 +177,57 @@ void DependencyCollector::attachToASTReader(ASTReader &R) { R.addListener(llvm::make_unique(*this)); } -namespace { -/// Private implementation for DependencyFileGenerator -class DFGImpl : public PPCallbacks { - std::vector Files; - llvm::StringSet<> FilesSet; - const Preprocessor *PP; - std::string OutputFile; - std::vector Targets; - bool IncludeSystemHeaders; - bool PhonyTarget; - bool AddMissingHeaderDeps; - bool SeenMissingHeader; - bool IncludeModuleFiles; - DependencyOutputFormat OutputFormat; - unsigned InputFileIndex; - -private: - bool FileMatchesDepCriteria(const char *Filename, - SrcMgr::CharacteristicKind FileType); - void OutputDependencyFile(); - -public: - DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts) - : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets), +DependencyFileGenerator::DependencyFileGenerator( + const DependencyOutputOptions &Opts) + : OutputFile(Opts.OutputFile), Targets(Opts.Targets), IncludeSystemHeaders(Opts.IncludeSystemHeaders), PhonyTarget(Opts.UsePhonyTargets), - AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), - SeenMissingHeader(false), + AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false), IncludeModuleFiles(Opts.IncludeModuleFiles), - OutputFormat(Opts.OutputFormat), - InputFileIndex(0) { - for (const auto &ExtraDep : Opts.ExtraDeps) { - if (AddFilename(ExtraDep)) - ++InputFileIndex; - } - } - - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override; - - void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok, - SrcMgr::CharacteristicKind FileType) override; - - void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, - StringRef FileName, bool IsAngled, - CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) override; - - void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled, - const FileEntry *File, - SrcMgr::CharacteristicKind FileType) override; - - void EndOfMainFile() override { - OutputDependencyFile(); - } - - bool AddFilename(StringRef Filename); - bool includeSystemHeaders() const { return IncludeSystemHeaders; } - bool includeModuleFiles() const { return IncludeModuleFiles; } -}; - -class DFGMMCallback : public ModuleMapCallbacks { - DFGImpl &Parent; -public: - DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {} - void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry, - bool IsSystem) override { - if (!IsSystem || Parent.includeSystemHeaders()) - Parent.AddFilename(Entry.getName()); - } -}; - -class DFGASTReaderListener : public ASTReaderListener { - DFGImpl &Parent; -public: - DFGASTReaderListener(DFGImpl &Parent) - : Parent(Parent) { } - bool needsInputFileVisitation() override { return true; } - bool needsSystemInputFileVisitation() override { - return Parent.includeSystemHeaders(); + OutputFormat(Opts.OutputFormat), InputFileIndex(0) { + for (const auto &ExtraDep : Opts.ExtraDeps) { + if (addDependency(ExtraDep)) + ++InputFileIndex; } - void visitModuleFile(StringRef Filename, - serialization::ModuleKind Kind) override; - bool visitInputFile(StringRef Filename, bool isSystem, - bool isOverridden, bool isExplicitModule) override; -}; } -DependencyFileGenerator::DependencyFileGenerator(void *Impl) -: Impl(Impl) { } - -DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor( - clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) { - - if (Opts.Targets.empty()) { +void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) { + if (Targets.empty()) { PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT); - return nullptr; + return; } // Disable the "file not found" diagnostic if the -MG option was given. - if (Opts.AddMissingHeaderDeps) + if (AddMissingHeaderDeps) PP.SetSuppressIncludeNotFoundError(true); - DFGImpl *Callback = new DFGImpl(&PP, Opts); - PP.addPPCallbacks(std::unique_ptr(Callback)); - PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( - llvm::make_unique(*Callback)); - return new DependencyFileGenerator(Callback); + DependencyCollector::attachToPreprocessor(PP); } -void DependencyFileGenerator::AttachToASTReader(ASTReader &R) { - DFGImpl *I = reinterpret_cast(Impl); - assert(I && "missing implementation"); - R.addListener(llvm::make_unique(*I)); -} +bool DependencyFileGenerator::sawDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, + bool IsMissing) { + if (IsMissing) { + // Handle the case of missing file from an inclusion directive. + if (AddMissingHeaderDeps) + return true; + SeenMissingHeader = true; + return false; + } + if (IsModuleFile && !IncludeModuleFiles) + return false; -/// FileMatchesDepCriteria - Determine whether the given Filename should be -/// considered as a dependency. -bool DFGImpl::FileMatchesDepCriteria(const char *Filename, - SrcMgr::CharacteristicKind FileType) { if (isSpecialFilename(Filename)) return false; if (IncludeSystemHeaders) return true; - return !isSystem(FileType); -} - -void DFGImpl::FileChanged(SourceLocation Loc, - FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) { - if (Reason != PPCallbacks::EnterFile) - return; - - // Dependency generation really does want to go all the way to the - // file entry for a source location to find out what is depended on. - // We do not want #line markers to affect dependency generation! - SourceManager &SM = PP->getSourceManager(); - - const FileEntry *FE = - SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc))); - if (!FE) return; - - StringRef Filename = FE->getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); + return !IsSystem; } -void DFGImpl::FileSkipped(const FileEntry &SkippedFile, - const Token &FilenameTok, - SrcMgr::CharacteristicKind FileType) { - StringRef Filename = SkippedFile.getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); -} - -void DFGImpl::InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) { - if (!File) { - if (AddMissingHeaderDeps) - AddFilename(FileName); - else - SeenMissingHeader = true; - } -} - -void DFGImpl::HasInclude(SourceLocation Loc, StringRef SpelledFilename, - bool IsAngled, const FileEntry *File, - SrcMgr::CharacteristicKind FileType) { - if (!File) - return; - StringRef Filename = File->getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); -} - -bool DFGImpl::AddFilename(StringRef Filename) { - if (FilesSet.insert(Filename).second) { - Files.push_back(Filename); - return true; - } - return false; +void DependencyFileGenerator::finishedMainFile(DiagnosticsEngine &Diags) { + outputDependencyFile(Diags); } /// Print the filename, with escaping or quoting that accommodates the three @@ -428,7 +309,7 @@ static void PrintFilename(raw_ostream &OS, StringRef Filename, } } -void DFGImpl::OutputDependencyFile() { +void DependencyFileGenerator::outputDependencyFile(DiagnosticsEngine &Diags) { if (SeenMissingHeader) { llvm::sys::fs::remove(OutputFile); return; @@ -437,8 +318,7 @@ void DFGImpl::OutputDependencyFile() { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text); if (EC) { - PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile - << EC.message(); + Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message(); return; } @@ -469,6 +349,7 @@ void DFGImpl::OutputDependencyFile() { // Now add each dependency in the order it was seen, but avoiding // duplicates. + ArrayRef Files = getDependencies(); for (StringRef File : Files) { // Start a new line if this would exceed the column limit. Make // sure to leave space for a trailing " \" in case we need to @@ -496,20 +377,3 @@ void DFGImpl::OutputDependencyFile() { } } } - -bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename, - bool IsSystem, bool IsOverridden, - bool IsExplicitModule) { - assert(!IsSystem || needsSystemInputFileVisitation()); - if (IsOverridden || IsExplicitModule) - return true; - - Parent.AddFilename(Filename); - return true; -} - -void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename, - serialization::ModuleKind Kind) { - if (Parent.includeModuleFiles()) - Parent.AddFilename(Filename); -}