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
llvm-svn: 363840
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 2eb1349..eb49c53 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -124,9 +124,6 @@
/// The module provider.
std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations;
- /// The dependency file generator.
- std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator;
-
std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors;
/// The set of top-level modules that has already been loaded,
@@ -661,7 +658,6 @@
InMemoryModuleCache &ModuleCache, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
- DependencyFileGenerator *DependencyFile,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex);
diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h
index 124d4a9..951d51b 100644
--- a/clang/include/clang/Frontend/Utils.h
+++ b/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: Migrate 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,25 +105,45 @@
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<std::string> 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
-
- DependencyFileGenerator(void *Impl);
-
+class DependencyFileGenerator : public DependencyCollector {
public:
- static DependencyFileGenerator *CreateAndAttachToPreprocessor(
- Preprocessor &PP, const DependencyOutputOptions &Opts);
+ DependencyFileGenerator(const DependencyOutputOptions &Opts);
- void AttachToASTReader(ASTReader &R);
+ void attachToPreprocessor(Preprocessor &PP) override;
+
+ void finishedMainFile(DiagnosticsEngine &Diags) override;
+
+ 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<std::string> 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/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index fd33b85..9cbc9ed 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/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<DependencyFileGenerator>(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<ASTReader> CompilerInstance::createPCHExternalASTSource(
@@ -501,7 +500,6 @@
InMemoryModuleCache &ModuleCache, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
- DependencyFileGenerator *DependencyFile,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex) {
@@ -521,8 +519,6 @@
static_cast<ASTDeserializationListener *>(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);
}
diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp
index 363aff7..b52e25b 100644
--- a/clang/lib/Frontend/DependencyFile.cpp
+++ b/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<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
+ PP.addPPCallbacks(llvm::make_unique<DepCollectorPPCallbacks>(
+ *this, PP.getSourceManager(), PP.getDiagnostics()));
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
llvm::make_unique<DepCollectorMMCallbacks>(*this));
}
@@ -147,206 +177,57 @@
R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
}
-namespace {
-/// Private implementation for DependencyFileGenerator
-class DFGImpl : public PPCallbacks {
- std::vector<std::string> Files;
- llvm::StringSet<> FilesSet;
- const Preprocessor *PP;
- std::string OutputFile;
- std::vector<std::string> 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;
- }
+ OutputFormat(Opts.OutputFormat), InputFileIndex(0) {
+ for (const auto &ExtraDep : Opts.ExtraDeps) {
+ if (addDependency(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();
- }
- 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<PPCallbacks>(Callback));
- PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
- llvm::make_unique<DFGMMCallback>(*Callback));
- return new DependencyFileGenerator(Callback);
+ DependencyCollector::attachToPreprocessor(PP);
}
-void DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
- DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
- assert(I && "missing implementation");
- R.addListener(llvm::make_unique<DFGASTReaderListener>(*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);
+ return !IsSystem;
}
-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));
-}
-
-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<std::string> 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);
-}