1f4a2713aSLionel Sambuc //===--- DependencyFile.cpp - Generate dependency file --------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This code generates dependency files.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/Frontend/Utils.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
17f4a2713aSLionel Sambuc #include "clang/Frontend/DependencyOutputOptions.h"
18f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendDiagnostic.h"
19f4a2713aSLionel Sambuc #include "clang/Lex/DirectoryLookup.h"
20f4a2713aSLionel Sambuc #include "clang/Lex/LexDiagnostic.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/PPCallbacks.h"
22f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
23*0a6a1f1dSLionel Sambuc #include "clang/Serialization/ASTReader.h"
24f4a2713aSLionel Sambuc #include "llvm/ADT/StringSet.h"
25*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc using namespace clang;
31f4a2713aSLionel Sambuc
32f4a2713aSLionel Sambuc namespace {
33*0a6a1f1dSLionel Sambuc struct DepCollectorPPCallbacks : public PPCallbacks {
34*0a6a1f1dSLionel Sambuc DependencyCollector &DepCollector;
35*0a6a1f1dSLionel Sambuc SourceManager &SM;
DepCollectorPPCallbacks__anon8d4671bb0111::DepCollectorPPCallbacks36*0a6a1f1dSLionel Sambuc DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM)
37*0a6a1f1dSLionel Sambuc : DepCollector(L), SM(SM) { }
38*0a6a1f1dSLionel Sambuc
FileChanged__anon8d4671bb0111::DepCollectorPPCallbacks39*0a6a1f1dSLionel Sambuc void FileChanged(SourceLocation Loc, FileChangeReason Reason,
40*0a6a1f1dSLionel Sambuc SrcMgr::CharacteristicKind FileType,
41*0a6a1f1dSLionel Sambuc FileID PrevFID) override {
42*0a6a1f1dSLionel Sambuc if (Reason != PPCallbacks::EnterFile)
43*0a6a1f1dSLionel Sambuc return;
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambuc // Dependency generation really does want to go all the way to the
46*0a6a1f1dSLionel Sambuc // file entry for a source location to find out what is depended on.
47*0a6a1f1dSLionel Sambuc // We do not want #line markers to affect dependency generation!
48*0a6a1f1dSLionel Sambuc const FileEntry *FE =
49*0a6a1f1dSLionel Sambuc SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
50*0a6a1f1dSLionel Sambuc if (!FE)
51*0a6a1f1dSLionel Sambuc return;
52*0a6a1f1dSLionel Sambuc
53*0a6a1f1dSLionel Sambuc StringRef Filename = FE->getName();
54*0a6a1f1dSLionel Sambuc
55*0a6a1f1dSLionel Sambuc // Remove leading "./" (or ".//" or "././" etc.)
56*0a6a1f1dSLionel Sambuc while (Filename.size() > 2 && Filename[0] == '.' &&
57*0a6a1f1dSLionel Sambuc llvm::sys::path::is_separator(Filename[1])) {
58*0a6a1f1dSLionel Sambuc Filename = Filename.substr(1);
59*0a6a1f1dSLionel Sambuc while (llvm::sys::path::is_separator(Filename[0]))
60*0a6a1f1dSLionel Sambuc Filename = Filename.substr(1);
61*0a6a1f1dSLionel Sambuc }
62*0a6a1f1dSLionel Sambuc
63*0a6a1f1dSLionel Sambuc DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
64*0a6a1f1dSLionel Sambuc FileType != SrcMgr::C_User,
65*0a6a1f1dSLionel Sambuc /*IsModuleFile*/false, /*IsMissing*/false);
66*0a6a1f1dSLionel Sambuc }
67*0a6a1f1dSLionel Sambuc
InclusionDirective__anon8d4671bb0111::DepCollectorPPCallbacks68*0a6a1f1dSLionel Sambuc void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
69*0a6a1f1dSLionel Sambuc StringRef FileName, bool IsAngled,
70*0a6a1f1dSLionel Sambuc CharSourceRange FilenameRange, const FileEntry *File,
71*0a6a1f1dSLionel Sambuc StringRef SearchPath, StringRef RelativePath,
72*0a6a1f1dSLionel Sambuc const Module *Imported) override {
73*0a6a1f1dSLionel Sambuc if (!File)
74*0a6a1f1dSLionel Sambuc DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
75*0a6a1f1dSLionel Sambuc /*IsSystem*/false, /*IsModuleFile*/false,
76*0a6a1f1dSLionel Sambuc /*IsMissing*/true);
77*0a6a1f1dSLionel Sambuc // Files that actually exist are handled by FileChanged.
78*0a6a1f1dSLionel Sambuc }
79*0a6a1f1dSLionel Sambuc
EndOfMainFile__anon8d4671bb0111::DepCollectorPPCallbacks80*0a6a1f1dSLionel Sambuc void EndOfMainFile() override {
81*0a6a1f1dSLionel Sambuc DepCollector.finishedMainFile();
82*0a6a1f1dSLionel Sambuc }
83*0a6a1f1dSLionel Sambuc };
84*0a6a1f1dSLionel Sambuc
85*0a6a1f1dSLionel Sambuc struct DepCollectorASTListener : public ASTReaderListener {
86*0a6a1f1dSLionel Sambuc DependencyCollector &DepCollector;
DepCollectorASTListener__anon8d4671bb0111::DepCollectorASTListener87*0a6a1f1dSLionel Sambuc DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
needsInputFileVisitation__anon8d4671bb0111::DepCollectorASTListener88*0a6a1f1dSLionel Sambuc bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation__anon8d4671bb0111::DepCollectorASTListener89*0a6a1f1dSLionel Sambuc bool needsSystemInputFileVisitation() override {
90*0a6a1f1dSLionel Sambuc return DepCollector.needSystemDependencies();
91*0a6a1f1dSLionel Sambuc }
visitModuleFile__anon8d4671bb0111::DepCollectorASTListener92*0a6a1f1dSLionel Sambuc void visitModuleFile(StringRef Filename) override {
93*0a6a1f1dSLionel Sambuc DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
94*0a6a1f1dSLionel Sambuc /*IsSystem*/false, /*IsModuleFile*/true,
95*0a6a1f1dSLionel Sambuc /*IsMissing*/false);
96*0a6a1f1dSLionel Sambuc }
visitInputFile__anon8d4671bb0111::DepCollectorASTListener97*0a6a1f1dSLionel Sambuc bool visitInputFile(StringRef Filename, bool IsSystem,
98*0a6a1f1dSLionel Sambuc bool IsOverridden) override {
99*0a6a1f1dSLionel Sambuc if (IsOverridden)
100*0a6a1f1dSLionel Sambuc return true;
101*0a6a1f1dSLionel Sambuc
102*0a6a1f1dSLionel Sambuc DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
103*0a6a1f1dSLionel Sambuc /*IsModuleFile*/false, /*IsMissing*/false);
104*0a6a1f1dSLionel Sambuc return true;
105*0a6a1f1dSLionel Sambuc }
106*0a6a1f1dSLionel Sambuc };
107*0a6a1f1dSLionel Sambuc } // end anonymous namespace
108*0a6a1f1dSLionel Sambuc
maybeAddDependency(StringRef Filename,bool FromModule,bool IsSystem,bool IsModuleFile,bool IsMissing)109*0a6a1f1dSLionel Sambuc void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
110*0a6a1f1dSLionel Sambuc bool IsSystem, bool IsModuleFile,
111*0a6a1f1dSLionel Sambuc bool IsMissing) {
112*0a6a1f1dSLionel Sambuc if (Seen.insert(Filename).second &&
113*0a6a1f1dSLionel Sambuc sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
114*0a6a1f1dSLionel Sambuc Dependencies.push_back(Filename);
115*0a6a1f1dSLionel Sambuc }
116*0a6a1f1dSLionel Sambuc
isSpecialFilename(StringRef Filename)117*0a6a1f1dSLionel Sambuc static bool isSpecialFilename(StringRef Filename) {
118*0a6a1f1dSLionel Sambuc return llvm::StringSwitch<bool>(Filename)
119*0a6a1f1dSLionel Sambuc .Case("<built-in>", true)
120*0a6a1f1dSLionel Sambuc .Case("<stdin>", true)
121*0a6a1f1dSLionel Sambuc .Default(false);
122*0a6a1f1dSLionel Sambuc }
123*0a6a1f1dSLionel Sambuc
sawDependency(StringRef Filename,bool FromModule,bool IsSystem,bool IsModuleFile,bool IsMissing)124*0a6a1f1dSLionel Sambuc bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
125*0a6a1f1dSLionel Sambuc bool IsSystem, bool IsModuleFile,
126*0a6a1f1dSLionel Sambuc bool IsMissing) {
127*0a6a1f1dSLionel Sambuc return !isSpecialFilename(Filename) &&
128*0a6a1f1dSLionel Sambuc (needSystemDependencies() || !IsSystem);
129*0a6a1f1dSLionel Sambuc }
130*0a6a1f1dSLionel Sambuc
~DependencyCollector()131*0a6a1f1dSLionel Sambuc DependencyCollector::~DependencyCollector() { }
attachToPreprocessor(Preprocessor & PP)132*0a6a1f1dSLionel Sambuc void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
133*0a6a1f1dSLionel Sambuc PP.addPPCallbacks(
134*0a6a1f1dSLionel Sambuc llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
135*0a6a1f1dSLionel Sambuc }
attachToASTReader(ASTReader & R)136*0a6a1f1dSLionel Sambuc void DependencyCollector::attachToASTReader(ASTReader &R) {
137*0a6a1f1dSLionel Sambuc R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
138*0a6a1f1dSLionel Sambuc }
139*0a6a1f1dSLionel Sambuc
140*0a6a1f1dSLionel Sambuc namespace {
141*0a6a1f1dSLionel Sambuc /// Private implementation for DependencyFileGenerator
142*0a6a1f1dSLionel Sambuc class DFGImpl : public PPCallbacks {
143f4a2713aSLionel Sambuc std::vector<std::string> Files;
144f4a2713aSLionel Sambuc llvm::StringSet<> FilesSet;
145f4a2713aSLionel Sambuc const Preprocessor *PP;
146f4a2713aSLionel Sambuc std::string OutputFile;
147f4a2713aSLionel Sambuc std::vector<std::string> Targets;
148f4a2713aSLionel Sambuc bool IncludeSystemHeaders;
149f4a2713aSLionel Sambuc bool PhonyTarget;
150f4a2713aSLionel Sambuc bool AddMissingHeaderDeps;
151f4a2713aSLionel Sambuc bool SeenMissingHeader;
152*0a6a1f1dSLionel Sambuc bool IncludeModuleFiles;
153f4a2713aSLionel Sambuc private:
154f4a2713aSLionel Sambuc bool FileMatchesDepCriteria(const char *Filename,
155f4a2713aSLionel Sambuc SrcMgr::CharacteristicKind FileType);
156f4a2713aSLionel Sambuc void OutputDependencyFile();
157f4a2713aSLionel Sambuc
158f4a2713aSLionel Sambuc public:
DFGImpl(const Preprocessor * _PP,const DependencyOutputOptions & Opts)159*0a6a1f1dSLionel Sambuc DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts)
160f4a2713aSLionel Sambuc : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets),
161f4a2713aSLionel Sambuc IncludeSystemHeaders(Opts.IncludeSystemHeaders),
162f4a2713aSLionel Sambuc PhonyTarget(Opts.UsePhonyTargets),
163f4a2713aSLionel Sambuc AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
164*0a6a1f1dSLionel Sambuc SeenMissingHeader(false),
165*0a6a1f1dSLionel Sambuc IncludeModuleFiles(Opts.IncludeModuleFiles) {}
166f4a2713aSLionel Sambuc
167*0a6a1f1dSLionel Sambuc void FileChanged(SourceLocation Loc, FileChangeReason Reason,
168f4a2713aSLionel Sambuc SrcMgr::CharacteristicKind FileType,
169*0a6a1f1dSLionel Sambuc FileID PrevFID) override;
170*0a6a1f1dSLionel Sambuc void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
171*0a6a1f1dSLionel Sambuc StringRef FileName, bool IsAngled,
172*0a6a1f1dSLionel Sambuc CharSourceRange FilenameRange, const FileEntry *File,
173*0a6a1f1dSLionel Sambuc StringRef SearchPath, StringRef RelativePath,
174*0a6a1f1dSLionel Sambuc const Module *Imported) override;
175f4a2713aSLionel Sambuc
EndOfMainFile()176*0a6a1f1dSLionel Sambuc void EndOfMainFile() override {
177f4a2713aSLionel Sambuc OutputDependencyFile();
178f4a2713aSLionel Sambuc }
179*0a6a1f1dSLionel Sambuc
180*0a6a1f1dSLionel Sambuc void AddFilename(StringRef Filename);
includeSystemHeaders() const181*0a6a1f1dSLionel Sambuc bool includeSystemHeaders() const { return IncludeSystemHeaders; }
includeModuleFiles() const182*0a6a1f1dSLionel Sambuc bool includeModuleFiles() const { return IncludeModuleFiles; }
183*0a6a1f1dSLionel Sambuc };
184*0a6a1f1dSLionel Sambuc
185*0a6a1f1dSLionel Sambuc class DFGASTReaderListener : public ASTReaderListener {
186*0a6a1f1dSLionel Sambuc DFGImpl &Parent;
187*0a6a1f1dSLionel Sambuc public:
DFGASTReaderListener(DFGImpl & Parent)188*0a6a1f1dSLionel Sambuc DFGASTReaderListener(DFGImpl &Parent)
189*0a6a1f1dSLionel Sambuc : Parent(Parent) { }
needsInputFileVisitation()190*0a6a1f1dSLionel Sambuc bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation()191*0a6a1f1dSLionel Sambuc bool needsSystemInputFileVisitation() override {
192*0a6a1f1dSLionel Sambuc return Parent.includeSystemHeaders();
193*0a6a1f1dSLionel Sambuc }
194*0a6a1f1dSLionel Sambuc void visitModuleFile(StringRef Filename) override;
195*0a6a1f1dSLionel Sambuc bool visitInputFile(StringRef Filename, bool isSystem,
196*0a6a1f1dSLionel Sambuc bool isOverridden) override;
197f4a2713aSLionel Sambuc };
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc
DependencyFileGenerator(void * Impl)200*0a6a1f1dSLionel Sambuc DependencyFileGenerator::DependencyFileGenerator(void *Impl)
201*0a6a1f1dSLionel Sambuc : Impl(Impl) { }
202*0a6a1f1dSLionel Sambuc
CreateAndAttachToPreprocessor(clang::Preprocessor & PP,const clang::DependencyOutputOptions & Opts)203*0a6a1f1dSLionel Sambuc DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
204*0a6a1f1dSLionel Sambuc clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) {
205*0a6a1f1dSLionel Sambuc
206f4a2713aSLionel Sambuc if (Opts.Targets.empty()) {
207f4a2713aSLionel Sambuc PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
208*0a6a1f1dSLionel Sambuc return nullptr;
209f4a2713aSLionel Sambuc }
210f4a2713aSLionel Sambuc
211f4a2713aSLionel Sambuc // Disable the "file not found" diagnostic if the -MG option was given.
212f4a2713aSLionel Sambuc if (Opts.AddMissingHeaderDeps)
213f4a2713aSLionel Sambuc PP.SetSuppressIncludeNotFoundError(true);
214f4a2713aSLionel Sambuc
215*0a6a1f1dSLionel Sambuc DFGImpl *Callback = new DFGImpl(&PP, Opts);
216*0a6a1f1dSLionel Sambuc PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback));
217*0a6a1f1dSLionel Sambuc return new DependencyFileGenerator(Callback);
218*0a6a1f1dSLionel Sambuc }
219*0a6a1f1dSLionel Sambuc
AttachToASTReader(ASTReader & R)220*0a6a1f1dSLionel Sambuc void DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
221*0a6a1f1dSLionel Sambuc DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
222*0a6a1f1dSLionel Sambuc assert(I && "missing implementation");
223*0a6a1f1dSLionel Sambuc R.addListener(llvm::make_unique<DFGASTReaderListener>(*I));
224f4a2713aSLionel Sambuc }
225f4a2713aSLionel Sambuc
226f4a2713aSLionel Sambuc /// FileMatchesDepCriteria - Determine whether the given Filename should be
227f4a2713aSLionel Sambuc /// considered as a dependency.
FileMatchesDepCriteria(const char * Filename,SrcMgr::CharacteristicKind FileType)228*0a6a1f1dSLionel Sambuc bool DFGImpl::FileMatchesDepCriteria(const char *Filename,
229f4a2713aSLionel Sambuc SrcMgr::CharacteristicKind FileType) {
230*0a6a1f1dSLionel Sambuc if (isSpecialFilename(Filename))
231f4a2713aSLionel Sambuc return false;
232f4a2713aSLionel Sambuc
233f4a2713aSLionel Sambuc if (IncludeSystemHeaders)
234f4a2713aSLionel Sambuc return true;
235f4a2713aSLionel Sambuc
236f4a2713aSLionel Sambuc return FileType == SrcMgr::C_User;
237f4a2713aSLionel Sambuc }
238f4a2713aSLionel Sambuc
FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID)239*0a6a1f1dSLionel Sambuc void DFGImpl::FileChanged(SourceLocation Loc,
240f4a2713aSLionel Sambuc FileChangeReason Reason,
241f4a2713aSLionel Sambuc SrcMgr::CharacteristicKind FileType,
242f4a2713aSLionel Sambuc FileID PrevFID) {
243f4a2713aSLionel Sambuc if (Reason != PPCallbacks::EnterFile)
244f4a2713aSLionel Sambuc return;
245f4a2713aSLionel Sambuc
246f4a2713aSLionel Sambuc // Dependency generation really does want to go all the way to the
247f4a2713aSLionel Sambuc // file entry for a source location to find out what is depended on.
248f4a2713aSLionel Sambuc // We do not want #line markers to affect dependency generation!
249f4a2713aSLionel Sambuc SourceManager &SM = PP->getSourceManager();
250f4a2713aSLionel Sambuc
251f4a2713aSLionel Sambuc const FileEntry *FE =
252f4a2713aSLionel Sambuc SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
253*0a6a1f1dSLionel Sambuc if (!FE) return;
254f4a2713aSLionel Sambuc
255f4a2713aSLionel Sambuc StringRef Filename = FE->getName();
256f4a2713aSLionel Sambuc if (!FileMatchesDepCriteria(Filename.data(), FileType))
257f4a2713aSLionel Sambuc return;
258f4a2713aSLionel Sambuc
259f4a2713aSLionel Sambuc // Remove leading "./" (or ".//" or "././" etc.)
260f4a2713aSLionel Sambuc while (Filename.size() > 2 && Filename[0] == '.' &&
261f4a2713aSLionel Sambuc llvm::sys::path::is_separator(Filename[1])) {
262f4a2713aSLionel Sambuc Filename = Filename.substr(1);
263f4a2713aSLionel Sambuc while (llvm::sys::path::is_separator(Filename[0]))
264f4a2713aSLionel Sambuc Filename = Filename.substr(1);
265f4a2713aSLionel Sambuc }
266f4a2713aSLionel Sambuc
267f4a2713aSLionel Sambuc AddFilename(Filename);
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,const FileEntry * File,StringRef SearchPath,StringRef RelativePath,const Module * Imported)270*0a6a1f1dSLionel Sambuc void DFGImpl::InclusionDirective(SourceLocation HashLoc,
271f4a2713aSLionel Sambuc const Token &IncludeTok,
272f4a2713aSLionel Sambuc StringRef FileName,
273f4a2713aSLionel Sambuc bool IsAngled,
274f4a2713aSLionel Sambuc CharSourceRange FilenameRange,
275f4a2713aSLionel Sambuc const FileEntry *File,
276f4a2713aSLionel Sambuc StringRef SearchPath,
277f4a2713aSLionel Sambuc StringRef RelativePath,
278f4a2713aSLionel Sambuc const Module *Imported) {
279f4a2713aSLionel Sambuc if (!File) {
280f4a2713aSLionel Sambuc if (AddMissingHeaderDeps)
281f4a2713aSLionel Sambuc AddFilename(FileName);
282f4a2713aSLionel Sambuc else
283f4a2713aSLionel Sambuc SeenMissingHeader = true;
284f4a2713aSLionel Sambuc }
285f4a2713aSLionel Sambuc }
286f4a2713aSLionel Sambuc
AddFilename(StringRef Filename)287*0a6a1f1dSLionel Sambuc void DFGImpl::AddFilename(StringRef Filename) {
288*0a6a1f1dSLionel Sambuc if (FilesSet.insert(Filename).second)
289f4a2713aSLionel Sambuc Files.push_back(Filename);
290f4a2713aSLionel Sambuc }
291f4a2713aSLionel Sambuc
292f4a2713aSLionel Sambuc /// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
293f4a2713aSLionel Sambuc /// other scary characters.
PrintFilename(raw_ostream & OS,StringRef Filename)294f4a2713aSLionel Sambuc static void PrintFilename(raw_ostream &OS, StringRef Filename) {
295f4a2713aSLionel Sambuc for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
296f4a2713aSLionel Sambuc if (Filename[i] == ' ' || Filename[i] == '#')
297f4a2713aSLionel Sambuc OS << '\\';
298f4a2713aSLionel Sambuc else if (Filename[i] == '$') // $ is escaped by $$.
299f4a2713aSLionel Sambuc OS << '$';
300f4a2713aSLionel Sambuc OS << Filename[i];
301f4a2713aSLionel Sambuc }
302f4a2713aSLionel Sambuc }
303f4a2713aSLionel Sambuc
OutputDependencyFile()304*0a6a1f1dSLionel Sambuc void DFGImpl::OutputDependencyFile() {
305f4a2713aSLionel Sambuc if (SeenMissingHeader) {
306*0a6a1f1dSLionel Sambuc llvm::sys::fs::remove(OutputFile);
307f4a2713aSLionel Sambuc return;
308f4a2713aSLionel Sambuc }
309f4a2713aSLionel Sambuc
310*0a6a1f1dSLionel Sambuc std::error_code EC;
311*0a6a1f1dSLionel Sambuc llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
312*0a6a1f1dSLionel Sambuc if (EC) {
313*0a6a1f1dSLionel Sambuc PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
314*0a6a1f1dSLionel Sambuc << EC.message();
315f4a2713aSLionel Sambuc return;
316f4a2713aSLionel Sambuc }
317f4a2713aSLionel Sambuc
318f4a2713aSLionel Sambuc // Write out the dependency targets, trying to avoid overly long
319f4a2713aSLionel Sambuc // lines when possible. We try our best to emit exactly the same
320f4a2713aSLionel Sambuc // dependency file as GCC (4.2), assuming the included files are the
321f4a2713aSLionel Sambuc // same.
322f4a2713aSLionel Sambuc const unsigned MaxColumns = 75;
323f4a2713aSLionel Sambuc unsigned Columns = 0;
324f4a2713aSLionel Sambuc
325f4a2713aSLionel Sambuc for (std::vector<std::string>::iterator
326f4a2713aSLionel Sambuc I = Targets.begin(), E = Targets.end(); I != E; ++I) {
327f4a2713aSLionel Sambuc unsigned N = I->length();
328f4a2713aSLionel Sambuc if (Columns == 0) {
329f4a2713aSLionel Sambuc Columns += N;
330f4a2713aSLionel Sambuc } else if (Columns + N + 2 > MaxColumns) {
331f4a2713aSLionel Sambuc Columns = N + 2;
332f4a2713aSLionel Sambuc OS << " \\\n ";
333f4a2713aSLionel Sambuc } else {
334f4a2713aSLionel Sambuc Columns += N + 1;
335f4a2713aSLionel Sambuc OS << ' ';
336f4a2713aSLionel Sambuc }
337f4a2713aSLionel Sambuc // Targets already quoted as needed.
338f4a2713aSLionel Sambuc OS << *I;
339f4a2713aSLionel Sambuc }
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc OS << ':';
342f4a2713aSLionel Sambuc Columns += 1;
343f4a2713aSLionel Sambuc
344f4a2713aSLionel Sambuc // Now add each dependency in the order it was seen, but avoiding
345f4a2713aSLionel Sambuc // duplicates.
346f4a2713aSLionel Sambuc for (std::vector<std::string>::iterator I = Files.begin(),
347f4a2713aSLionel Sambuc E = Files.end(); I != E; ++I) {
348f4a2713aSLionel Sambuc // Start a new line if this would exceed the column limit. Make
349f4a2713aSLionel Sambuc // sure to leave space for a trailing " \" in case we need to
350f4a2713aSLionel Sambuc // break the line on the next iteration.
351f4a2713aSLionel Sambuc unsigned N = I->length();
352f4a2713aSLionel Sambuc if (Columns + (N + 1) + 2 > MaxColumns) {
353f4a2713aSLionel Sambuc OS << " \\\n ";
354f4a2713aSLionel Sambuc Columns = 2;
355f4a2713aSLionel Sambuc }
356f4a2713aSLionel Sambuc OS << ' ';
357f4a2713aSLionel Sambuc PrintFilename(OS, *I);
358f4a2713aSLionel Sambuc Columns += N + 1;
359f4a2713aSLionel Sambuc }
360f4a2713aSLionel Sambuc OS << '\n';
361f4a2713aSLionel Sambuc
362f4a2713aSLionel Sambuc // Create phony targets if requested.
363f4a2713aSLionel Sambuc if (PhonyTarget && !Files.empty()) {
364f4a2713aSLionel Sambuc // Skip the first entry, this is always the input file itself.
365f4a2713aSLionel Sambuc for (std::vector<std::string>::iterator I = Files.begin() + 1,
366f4a2713aSLionel Sambuc E = Files.end(); I != E; ++I) {
367f4a2713aSLionel Sambuc OS << '\n';
368f4a2713aSLionel Sambuc PrintFilename(OS, *I);
369f4a2713aSLionel Sambuc OS << ":\n";
370f4a2713aSLionel Sambuc }
371f4a2713aSLionel Sambuc }
372f4a2713aSLionel Sambuc }
373f4a2713aSLionel Sambuc
visitInputFile(llvm::StringRef Filename,bool IsSystem,bool IsOverridden)374*0a6a1f1dSLionel Sambuc bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
375*0a6a1f1dSLionel Sambuc bool IsSystem, bool IsOverridden) {
376*0a6a1f1dSLionel Sambuc assert(!IsSystem || needsSystemInputFileVisitation());
377*0a6a1f1dSLionel Sambuc if (IsOverridden)
378*0a6a1f1dSLionel Sambuc return true;
379*0a6a1f1dSLionel Sambuc
380*0a6a1f1dSLionel Sambuc Parent.AddFilename(Filename);
381*0a6a1f1dSLionel Sambuc return true;
382*0a6a1f1dSLionel Sambuc }
383*0a6a1f1dSLionel Sambuc
visitModuleFile(llvm::StringRef Filename)384*0a6a1f1dSLionel Sambuc void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename) {
385*0a6a1f1dSLionel Sambuc if (Parent.includeModuleFiles())
386*0a6a1f1dSLionel Sambuc Parent.AddFilename(Filename);
387*0a6a1f1dSLionel Sambuc }
388