Index: clang/include/clang/Frontend/CompilerInstance.h =================================================================== --- clang/include/clang/Frontend/CompilerInstance.h +++ clang/include/clang/Frontend/CompilerInstance.h @@ -124,9 +124,6 @@ /// 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 @@ InMemoryModuleCache &ModuleCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, ArrayRef> Extensions, - DependencyFileGenerator *DependencyFile, ArrayRef> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex); Index: clang/include/clang/Frontend/Utils.h =================================================================== --- clang/include/clang/Frontend/Utils.h +++ clang/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 @@ class ASTReader; class CompilerInstance; class CompilerInvocation; -class DependencyOutputOptions; class DiagnosticsEngine; class ExternalSemaSource; class FrontendOptions; @@ -77,8 +77,7 @@ /// 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: DependencyGraphGen to use this interface. class DependencyCollector { public: virtual ~DependencyCollector(); @@ -95,7 +94,7 @@ 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,6 +105,11 @@ 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; @@ -115,16 +119,31 @@ /// 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 Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== --- clang/lib/Frontend/CompilerInstance.cpp +++ clang/lib/Frontend/CompilerInstance.cpp @@ -415,8 +415,7 @@ // 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 @@ 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 @@ 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 @@ static_cast(DeserializationListener), /*TakeOwnership=*/OwnDeserializationListener); - if (DependencyFile) - DependencyFile->AttachToASTReader(*Reader); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*Reader); @@ -1492,8 +1488,6 @@ if (hasASTConsumer()) ModuleManager->StartTranslationUnit(&getASTConsumer()); - if (TheDependencyFileGenerator) - TheDependencyFileGenerator->AttachToASTReader(*ModuleManager); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*ModuleManager); } Index: clang/lib/Frontend/DependencyFile.cpp =================================================================== --- clang/lib/Frontend/DependencyFile.cpp +++ clang/lib/Frontend/DependencyFile.cpp @@ -32,8 +32,10 @@ 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 @@ /*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 @@ // 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 @@ 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 @@ 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 @@ 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 @@ } } -void DFGImpl::OutputDependencyFile() { +void DependencyFileGenerator::outputDependencyFile(DiagnosticsEngine &Diags) { if (SeenMissingHeader) { llvm::sys::fs::remove(OutputFile); return; @@ -437,8 +318,7 @@ 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 @@ // 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 @@ } } } - -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); -}