24 #include "llvm/ADT/StringSet.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/Support/FileSystem.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/raw_ostream.h"
30 using namespace clang;
33 struct DepCollectorPPCallbacks :
public PPCallbacks {
37 : DepCollector(L), SM(SM) { }
53 StringRef Filename = FE->
getName();
56 while (Filename.size() > 2 && Filename[0] ==
'.' &&
57 llvm::sys::path::is_separator(Filename[1])) {
58 Filename = Filename.substr(1);
59 while (llvm::sys::path::is_separator(Filename[0]))
60 Filename = Filename.substr(1);
63 DepCollector.maybeAddDependency(Filename,
false,
69 StringRef FileName,
bool IsAngled,
71 StringRef SearchPath, StringRef RelativePath,
72 const Module *Imported)
override {
74 DepCollector.maybeAddDependency(FileName,
false,
80 void EndOfMainFile()
override {
81 DepCollector.finishedMainFile();
88 bool needsInputFileVisitation()
override {
return true; }
89 bool needsSystemInputFileVisitation()
override {
90 return DepCollector.needSystemDependencies();
92 void visitModuleFile(StringRef Filename)
override {
93 DepCollector.maybeAddDependency(Filename,
true,
97 bool visitInputFile(StringRef Filename,
bool IsSystem,
98 bool IsOverridden)
override {
102 DepCollector.maybeAddDependency(Filename,
true, IsSystem,
110 bool IsSystem,
bool IsModuleFile,
112 if (Seen.insert(Filename).second &&
113 sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
114 Dependencies.push_back(Filename);
118 return llvm::StringSwitch<bool>(Filename)
119 .Case(
"<built-in>",
true)
120 .Case(
"<stdin>",
true)
125 bool IsSystem,
bool IsModuleFile,
137 R.
addListener(llvm::make_unique<DepCollectorASTListener>(*
this));
143 std::vector<std::string> Files;
144 llvm::StringSet<> FilesSet;
146 std::string OutputFile;
147 std::vector<std::string> Targets;
148 bool IncludeSystemHeaders;
150 bool AddMissingHeaderDeps;
151 bool SeenMissingHeader;
152 bool IncludeModuleFiles;
156 bool FileMatchesDepCriteria(
const char *Filename,
158 void OutputDependencyFile();
162 : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets),
163 IncludeSystemHeaders(Opts.IncludeSystemHeaders),
164 PhonyTarget(Opts.UsePhonyTargets),
165 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
166 SeenMissingHeader(
false),
167 IncludeModuleFiles(Opts.IncludeModuleFiles),
168 OutputFormat(Opts.OutputFormat) {}
174 StringRef FileName,
bool IsAngled,
176 StringRef SearchPath, StringRef RelativePath,
177 const Module *Imported)
override;
179 void EndOfMainFile()
override {
180 OutputDependencyFile();
183 void AddFilename(StringRef Filename);
184 bool includeSystemHeaders()
const {
return IncludeSystemHeaders; }
185 bool includeModuleFiles()
const {
return IncludeModuleFiles; }
191 DFGASTReaderListener(DFGImpl &Parent)
193 bool needsInputFileVisitation()
override {
return true; }
194 bool needsSystemInputFileVisitation()
override {
195 return Parent.includeSystemHeaders();
197 void visitModuleFile(StringRef Filename)
override;
198 bool visitInputFile(StringRef Filename,
bool isSystem,
199 bool isOverridden)
override;
203 DependencyFileGenerator::DependencyFileGenerator(
void *Impl)
218 DFGImpl *
Callback =
new DFGImpl(&PP, Opts);
224 DFGImpl *I =
reinterpret_cast<DFGImpl *
>(Impl);
225 assert(I &&
"missing implementation");
226 R.
addListener(llvm::make_unique<DFGASTReaderListener>(*I));
231 bool DFGImpl::FileMatchesDepCriteria(
const char *Filename,
236 if (IncludeSystemHeaders)
243 FileChangeReason Reason,
258 StringRef Filename = FE->
getName();
259 if (!FileMatchesDepCriteria(Filename.data(), FileType))
263 while (Filename.size() > 2 && Filename[0] ==
'.' &&
264 llvm::sys::path::is_separator(Filename[1])) {
265 Filename = Filename.substr(1);
266 while (llvm::sys::path::is_separator(Filename[0]))
267 Filename = Filename.substr(1);
270 AddFilename(Filename);
274 const Token &IncludeTok,
279 StringRef SearchPath,
280 StringRef RelativePath,
283 if (AddMissingHeaderDeps)
284 AddFilename(FileName);
286 SeenMissingHeader =
true;
290 void DFGImpl::AddFilename(StringRef Filename) {
291 if (FilesSet.insert(Filename).second)
292 Files.push_back(Filename);
349 if (Filename.find_first_of(
" #${}^!") != StringRef::npos)
350 OS <<
'\"' << Filename <<
'\"';
356 for (
unsigned i = 0, e = Filename.size(); i != e; ++i) {
357 if (Filename[i] ==
'#')
359 else if (Filename[i] ==
' ') {
362 while (j > 0 && Filename[--j] ==
'\\')
364 }
else if (Filename[i] ==
'$')
370 void DFGImpl::OutputDependencyFile() {
371 if (SeenMissingHeader) {
372 llvm::sys::fs::remove(OutputFile);
377 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
379 PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
388 const unsigned MaxColumns = 75;
389 unsigned Columns = 0;
391 for (std::vector<std::string>::iterator
392 I = Targets.begin(), E = Targets.end(); I != E; ++I) {
393 unsigned N = I->length();
396 }
else if (Columns + N + 2 > MaxColumns) {
412 for (std::vector<std::string>::iterator I = Files.begin(),
413 E = Files.end(); I != E; ++I) {
417 unsigned N = I->length();
418 if (Columns + (N + 1) + 2 > MaxColumns) {
429 if (PhonyTarget && !Files.empty()) {
431 for (std::vector<std::string>::iterator I = Files.begin() + 1,
432 E = Files.end(); I != E; ++I) {
440 bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
441 bool IsSystem,
bool IsOverridden) {
442 assert(!IsSystem || needsSystemInputFileVisitation());
446 Parent.AddFilename(Filename);
450 void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename) {
451 if (Parent.includeModuleFiles())
452 Parent.AddFilename(Filename);
SourceManager & getSourceManager() const
Defines the clang::FileManager interface and associated types.
Defines the SourceManager interface.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
This interface provides a way to observe the actions of the preprocessor as it does its thing...
virtual bool needSystemDependencies()
Return true if system files should be passed to sawDependency().
Describes a module or submodule.
void SetSuppressIncludeNotFoundError(bool Suppress)
void attachToASTReader(ASTReader &R)
static DependencyFileGenerator * CreateAndAttachToPreprocessor(Preprocessor &PP, const DependencyOutputOptions &Opts)
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)
static bool isSpecialFilename(StringRef Filename)
Represents a character-granular source range.
MatchFinder::MatchCallback * Callback
Defines the clang::Preprocessor interface.
Record the location of an inclusion directive, such as an #include or #import statement.
void addListener(std::unique_ptr< ASTReaderListener > L)
Add an AST callback listener.
void AttachToASTReader(ASTReader &R)
const char * getName() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
Cached information about one file (either on disk or in the virtual file system). ...
DiagnosticsEngine & getDiagnostics() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Reads an AST files chain containing the contents of a translation unit.
virtual ~DependencyCollector()
Abstract interface for callback invocations by the ASTReader.
void attachToPreprocessor(Preprocessor &PP)
Defines the PPCallbacks interface.
std::vector< std::string > Targets
unsigned AddMissingHeaderDeps
Add missing headers to dependency list.
virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)
static void PrintFilename(raw_ostream &OS, StringRef Filename, DependencyOutputFormat OutputFormat)
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
DependencyOutputFormat
DependencyOutputFormat - Format for the compiler dependency file.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.