xref: /minix3/external/bsd/llvm/dist/clang/lib/Frontend/DependencyFile.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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