1*67e74705SXin Li //===--- DependencyFile.cpp - Generate dependency file --------------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This code generates dependency files.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "clang/Frontend/Utils.h"
15*67e74705SXin Li #include "clang/Basic/FileManager.h"
16*67e74705SXin Li #include "clang/Basic/SourceManager.h"
17*67e74705SXin Li #include "clang/Frontend/DependencyOutputOptions.h"
18*67e74705SXin Li #include "clang/Frontend/FrontendDiagnostic.h"
19*67e74705SXin Li #include "clang/Lex/DirectoryLookup.h"
20*67e74705SXin Li #include "clang/Lex/LexDiagnostic.h"
21*67e74705SXin Li #include "clang/Lex/ModuleMap.h"
22*67e74705SXin Li #include "clang/Lex/PPCallbacks.h"
23*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
24*67e74705SXin Li #include "clang/Serialization/ASTReader.h"
25*67e74705SXin Li #include "llvm/ADT/StringSet.h"
26*67e74705SXin Li #include "llvm/ADT/StringSwitch.h"
27*67e74705SXin Li #include "llvm/Support/FileSystem.h"
28*67e74705SXin Li #include "llvm/Support/Path.h"
29*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
30*67e74705SXin Li
31*67e74705SXin Li using namespace clang;
32*67e74705SXin Li
33*67e74705SXin Li namespace {
34*67e74705SXin Li struct DepCollectorPPCallbacks : public PPCallbacks {
35*67e74705SXin Li DependencyCollector &DepCollector;
36*67e74705SXin Li SourceManager &SM;
DepCollectorPPCallbacks__anon907f08a00111::DepCollectorPPCallbacks37*67e74705SXin Li DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM)
38*67e74705SXin Li : DepCollector(L), SM(SM) { }
39*67e74705SXin Li
FileChanged__anon907f08a00111::DepCollectorPPCallbacks40*67e74705SXin Li void FileChanged(SourceLocation Loc, FileChangeReason Reason,
41*67e74705SXin Li SrcMgr::CharacteristicKind FileType,
42*67e74705SXin Li FileID PrevFID) override {
43*67e74705SXin Li if (Reason != PPCallbacks::EnterFile)
44*67e74705SXin Li return;
45*67e74705SXin Li
46*67e74705SXin Li // Dependency generation really does want to go all the way to the
47*67e74705SXin Li // file entry for a source location to find out what is depended on.
48*67e74705SXin Li // We do not want #line markers to affect dependency generation!
49*67e74705SXin Li const FileEntry *FE =
50*67e74705SXin Li SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
51*67e74705SXin Li if (!FE)
52*67e74705SXin Li return;
53*67e74705SXin Li
54*67e74705SXin Li StringRef Filename =
55*67e74705SXin Li llvm::sys::path::remove_leading_dotslash(FE->getName());
56*67e74705SXin Li
57*67e74705SXin Li DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
58*67e74705SXin Li FileType != SrcMgr::C_User,
59*67e74705SXin Li /*IsModuleFile*/false, /*IsMissing*/false);
60*67e74705SXin Li }
61*67e74705SXin Li
InclusionDirective__anon907f08a00111::DepCollectorPPCallbacks62*67e74705SXin Li void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
63*67e74705SXin Li StringRef FileName, bool IsAngled,
64*67e74705SXin Li CharSourceRange FilenameRange, const FileEntry *File,
65*67e74705SXin Li StringRef SearchPath, StringRef RelativePath,
66*67e74705SXin Li const Module *Imported) override {
67*67e74705SXin Li if (!File)
68*67e74705SXin Li DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
69*67e74705SXin Li /*IsSystem*/false, /*IsModuleFile*/false,
70*67e74705SXin Li /*IsMissing*/true);
71*67e74705SXin Li // Files that actually exist are handled by FileChanged.
72*67e74705SXin Li }
73*67e74705SXin Li
EndOfMainFile__anon907f08a00111::DepCollectorPPCallbacks74*67e74705SXin Li void EndOfMainFile() override {
75*67e74705SXin Li DepCollector.finishedMainFile();
76*67e74705SXin Li }
77*67e74705SXin Li };
78*67e74705SXin Li
79*67e74705SXin Li struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
80*67e74705SXin Li DependencyCollector &DepCollector;
DepCollectorMMCallbacks__anon907f08a00111::DepCollectorMMCallbacks81*67e74705SXin Li DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
82*67e74705SXin Li
moduleMapFileRead__anon907f08a00111::DepCollectorMMCallbacks83*67e74705SXin Li void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
84*67e74705SXin Li bool IsSystem) override {
85*67e74705SXin Li StringRef Filename = Entry.getName();
86*67e74705SXin Li DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
87*67e74705SXin Li /*IsSystem*/IsSystem,
88*67e74705SXin Li /*IsModuleFile*/false,
89*67e74705SXin Li /*IsMissing*/false);
90*67e74705SXin Li }
91*67e74705SXin Li };
92*67e74705SXin Li
93*67e74705SXin Li struct DepCollectorASTListener : public ASTReaderListener {
94*67e74705SXin Li DependencyCollector &DepCollector;
DepCollectorASTListener__anon907f08a00111::DepCollectorASTListener95*67e74705SXin Li DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
needsInputFileVisitation__anon907f08a00111::DepCollectorASTListener96*67e74705SXin Li bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation__anon907f08a00111::DepCollectorASTListener97*67e74705SXin Li bool needsSystemInputFileVisitation() override {
98*67e74705SXin Li return DepCollector.needSystemDependencies();
99*67e74705SXin Li }
visitModuleFile__anon907f08a00111::DepCollectorASTListener100*67e74705SXin Li void visitModuleFile(StringRef Filename,
101*67e74705SXin Li serialization::ModuleKind Kind) override {
102*67e74705SXin Li DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
103*67e74705SXin Li /*IsSystem*/false, /*IsModuleFile*/true,
104*67e74705SXin Li /*IsMissing*/false);
105*67e74705SXin Li }
visitInputFile__anon907f08a00111::DepCollectorASTListener106*67e74705SXin Li bool visitInputFile(StringRef Filename, bool IsSystem,
107*67e74705SXin Li bool IsOverridden, bool IsExplicitModule) override {
108*67e74705SXin Li if (IsOverridden || IsExplicitModule)
109*67e74705SXin Li return true;
110*67e74705SXin Li
111*67e74705SXin Li DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
112*67e74705SXin Li /*IsModuleFile*/false, /*IsMissing*/false);
113*67e74705SXin Li return true;
114*67e74705SXin Li }
115*67e74705SXin Li };
116*67e74705SXin Li } // end anonymous namespace
117*67e74705SXin Li
maybeAddDependency(StringRef Filename,bool FromModule,bool IsSystem,bool IsModuleFile,bool IsMissing)118*67e74705SXin Li void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
119*67e74705SXin Li bool IsSystem, bool IsModuleFile,
120*67e74705SXin Li bool IsMissing) {
121*67e74705SXin Li if (Seen.insert(Filename).second &&
122*67e74705SXin Li sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
123*67e74705SXin Li Dependencies.push_back(Filename);
124*67e74705SXin Li }
125*67e74705SXin Li
isSpecialFilename(StringRef Filename)126*67e74705SXin Li static bool isSpecialFilename(StringRef Filename) {
127*67e74705SXin Li return llvm::StringSwitch<bool>(Filename)
128*67e74705SXin Li .Case("<built-in>", true)
129*67e74705SXin Li .Case("<stdin>", true)
130*67e74705SXin Li .Default(false);
131*67e74705SXin Li }
132*67e74705SXin Li
sawDependency(StringRef Filename,bool FromModule,bool IsSystem,bool IsModuleFile,bool IsMissing)133*67e74705SXin Li bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
134*67e74705SXin Li bool IsSystem, bool IsModuleFile,
135*67e74705SXin Li bool IsMissing) {
136*67e74705SXin Li return !isSpecialFilename(Filename) &&
137*67e74705SXin Li (needSystemDependencies() || !IsSystem);
138*67e74705SXin Li }
139*67e74705SXin Li
~DependencyCollector()140*67e74705SXin Li DependencyCollector::~DependencyCollector() { }
attachToPreprocessor(Preprocessor & PP)141*67e74705SXin Li void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
142*67e74705SXin Li PP.addPPCallbacks(
143*67e74705SXin Li llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
144*67e74705SXin Li PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
145*67e74705SXin Li llvm::make_unique<DepCollectorMMCallbacks>(*this));
146*67e74705SXin Li }
attachToASTReader(ASTReader & R)147*67e74705SXin Li void DependencyCollector::attachToASTReader(ASTReader &R) {
148*67e74705SXin Li R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
149*67e74705SXin Li }
150*67e74705SXin Li
151*67e74705SXin Li namespace {
152*67e74705SXin Li /// Private implementation for DependencyFileGenerator
153*67e74705SXin Li class DFGImpl : public PPCallbacks {
154*67e74705SXin Li std::vector<std::string> Files;
155*67e74705SXin Li llvm::StringSet<> FilesSet;
156*67e74705SXin Li const Preprocessor *PP;
157*67e74705SXin Li std::string OutputFile;
158*67e74705SXin Li std::vector<std::string> Targets;
159*67e74705SXin Li bool IncludeSystemHeaders;
160*67e74705SXin Li bool PhonyTarget;
161*67e74705SXin Li bool AddMissingHeaderDeps;
162*67e74705SXin Li bool SeenMissingHeader;
163*67e74705SXin Li bool IncludeModuleFiles;
164*67e74705SXin Li DependencyOutputFormat OutputFormat;
165*67e74705SXin Li
166*67e74705SXin Li private:
167*67e74705SXin Li bool FileMatchesDepCriteria(const char *Filename,
168*67e74705SXin Li SrcMgr::CharacteristicKind FileType);
169*67e74705SXin Li void OutputDependencyFile();
170*67e74705SXin Li
171*67e74705SXin Li public:
DFGImpl(const Preprocessor * _PP,const DependencyOutputOptions & Opts)172*67e74705SXin Li DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts)
173*67e74705SXin Li : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets),
174*67e74705SXin Li IncludeSystemHeaders(Opts.IncludeSystemHeaders),
175*67e74705SXin Li PhonyTarget(Opts.UsePhonyTargets),
176*67e74705SXin Li AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
177*67e74705SXin Li SeenMissingHeader(false),
178*67e74705SXin Li IncludeModuleFiles(Opts.IncludeModuleFiles),
179*67e74705SXin Li OutputFormat(Opts.OutputFormat) {
180*67e74705SXin Li for (const auto &ExtraDep : Opts.ExtraDeps) {
181*67e74705SXin Li AddFilename(ExtraDep);
182*67e74705SXin Li }
183*67e74705SXin Li }
184*67e74705SXin Li
185*67e74705SXin Li void FileChanged(SourceLocation Loc, FileChangeReason Reason,
186*67e74705SXin Li SrcMgr::CharacteristicKind FileType,
187*67e74705SXin Li FileID PrevFID) override;
188*67e74705SXin Li void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
189*67e74705SXin Li StringRef FileName, bool IsAngled,
190*67e74705SXin Li CharSourceRange FilenameRange, const FileEntry *File,
191*67e74705SXin Li StringRef SearchPath, StringRef RelativePath,
192*67e74705SXin Li const Module *Imported) override;
193*67e74705SXin Li
EndOfMainFile()194*67e74705SXin Li void EndOfMainFile() override {
195*67e74705SXin Li OutputDependencyFile();
196*67e74705SXin Li }
197*67e74705SXin Li
198*67e74705SXin Li void AddFilename(StringRef Filename);
includeSystemHeaders() const199*67e74705SXin Li bool includeSystemHeaders() const { return IncludeSystemHeaders; }
includeModuleFiles() const200*67e74705SXin Li bool includeModuleFiles() const { return IncludeModuleFiles; }
201*67e74705SXin Li };
202*67e74705SXin Li
203*67e74705SXin Li class DFGMMCallback : public ModuleMapCallbacks {
204*67e74705SXin Li DFGImpl &Parent;
205*67e74705SXin Li public:
DFGMMCallback(DFGImpl & Parent)206*67e74705SXin Li DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {}
moduleMapFileRead(SourceLocation Loc,const FileEntry & Entry,bool IsSystem)207*67e74705SXin Li void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
208*67e74705SXin Li bool IsSystem) override {
209*67e74705SXin Li if (!IsSystem || Parent.includeSystemHeaders())
210*67e74705SXin Li Parent.AddFilename(Entry.getName());
211*67e74705SXin Li }
212*67e74705SXin Li };
213*67e74705SXin Li
214*67e74705SXin Li class DFGASTReaderListener : public ASTReaderListener {
215*67e74705SXin Li DFGImpl &Parent;
216*67e74705SXin Li public:
DFGASTReaderListener(DFGImpl & Parent)217*67e74705SXin Li DFGASTReaderListener(DFGImpl &Parent)
218*67e74705SXin Li : Parent(Parent) { }
needsInputFileVisitation()219*67e74705SXin Li bool needsInputFileVisitation() override { return true; }
needsSystemInputFileVisitation()220*67e74705SXin Li bool needsSystemInputFileVisitation() override {
221*67e74705SXin Li return Parent.includeSystemHeaders();
222*67e74705SXin Li }
223*67e74705SXin Li void visitModuleFile(StringRef Filename,
224*67e74705SXin Li serialization::ModuleKind Kind) override;
225*67e74705SXin Li bool visitInputFile(StringRef Filename, bool isSystem,
226*67e74705SXin Li bool isOverridden, bool isExplicitModule) override;
227*67e74705SXin Li };
228*67e74705SXin Li }
229*67e74705SXin Li
DependencyFileGenerator(void * Impl)230*67e74705SXin Li DependencyFileGenerator::DependencyFileGenerator(void *Impl)
231*67e74705SXin Li : Impl(Impl) { }
232*67e74705SXin Li
CreateAndAttachToPreprocessor(clang::Preprocessor & PP,const clang::DependencyOutputOptions & Opts)233*67e74705SXin Li DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
234*67e74705SXin Li clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) {
235*67e74705SXin Li
236*67e74705SXin Li if (Opts.Targets.empty()) {
237*67e74705SXin Li PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
238*67e74705SXin Li return nullptr;
239*67e74705SXin Li }
240*67e74705SXin Li
241*67e74705SXin Li // Disable the "file not found" diagnostic if the -MG option was given.
242*67e74705SXin Li if (Opts.AddMissingHeaderDeps)
243*67e74705SXin Li PP.SetSuppressIncludeNotFoundError(true);
244*67e74705SXin Li
245*67e74705SXin Li DFGImpl *Callback = new DFGImpl(&PP, Opts);
246*67e74705SXin Li PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback));
247*67e74705SXin Li PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
248*67e74705SXin Li llvm::make_unique<DFGMMCallback>(*Callback));
249*67e74705SXin Li return new DependencyFileGenerator(Callback);
250*67e74705SXin Li }
251*67e74705SXin Li
AttachToASTReader(ASTReader & R)252*67e74705SXin Li void DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
253*67e74705SXin Li DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
254*67e74705SXin Li assert(I && "missing implementation");
255*67e74705SXin Li R.addListener(llvm::make_unique<DFGASTReaderListener>(*I));
256*67e74705SXin Li }
257*67e74705SXin Li
258*67e74705SXin Li /// FileMatchesDepCriteria - Determine whether the given Filename should be
259*67e74705SXin Li /// considered as a dependency.
FileMatchesDepCriteria(const char * Filename,SrcMgr::CharacteristicKind FileType)260*67e74705SXin Li bool DFGImpl::FileMatchesDepCriteria(const char *Filename,
261*67e74705SXin Li SrcMgr::CharacteristicKind FileType) {
262*67e74705SXin Li if (isSpecialFilename(Filename))
263*67e74705SXin Li return false;
264*67e74705SXin Li
265*67e74705SXin Li if (IncludeSystemHeaders)
266*67e74705SXin Li return true;
267*67e74705SXin Li
268*67e74705SXin Li return FileType == SrcMgr::C_User;
269*67e74705SXin Li }
270*67e74705SXin Li
FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID)271*67e74705SXin Li void DFGImpl::FileChanged(SourceLocation Loc,
272*67e74705SXin Li FileChangeReason Reason,
273*67e74705SXin Li SrcMgr::CharacteristicKind FileType,
274*67e74705SXin Li FileID PrevFID) {
275*67e74705SXin Li if (Reason != PPCallbacks::EnterFile)
276*67e74705SXin Li return;
277*67e74705SXin Li
278*67e74705SXin Li // Dependency generation really does want to go all the way to the
279*67e74705SXin Li // file entry for a source location to find out what is depended on.
280*67e74705SXin Li // We do not want #line markers to affect dependency generation!
281*67e74705SXin Li SourceManager &SM = PP->getSourceManager();
282*67e74705SXin Li
283*67e74705SXin Li const FileEntry *FE =
284*67e74705SXin Li SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
285*67e74705SXin Li if (!FE) return;
286*67e74705SXin Li
287*67e74705SXin Li StringRef Filename = FE->getName();
288*67e74705SXin Li if (!FileMatchesDepCriteria(Filename.data(), FileType))
289*67e74705SXin Li return;
290*67e74705SXin Li
291*67e74705SXin Li AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
292*67e74705SXin Li }
293*67e74705SXin Li
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,const FileEntry * File,StringRef SearchPath,StringRef RelativePath,const Module * Imported)294*67e74705SXin Li void DFGImpl::InclusionDirective(SourceLocation HashLoc,
295*67e74705SXin Li const Token &IncludeTok,
296*67e74705SXin Li StringRef FileName,
297*67e74705SXin Li bool IsAngled,
298*67e74705SXin Li CharSourceRange FilenameRange,
299*67e74705SXin Li const FileEntry *File,
300*67e74705SXin Li StringRef SearchPath,
301*67e74705SXin Li StringRef RelativePath,
302*67e74705SXin Li const Module *Imported) {
303*67e74705SXin Li if (!File) {
304*67e74705SXin Li if (AddMissingHeaderDeps)
305*67e74705SXin Li AddFilename(FileName);
306*67e74705SXin Li else
307*67e74705SXin Li SeenMissingHeader = true;
308*67e74705SXin Li }
309*67e74705SXin Li }
310*67e74705SXin Li
AddFilename(StringRef Filename)311*67e74705SXin Li void DFGImpl::AddFilename(StringRef Filename) {
312*67e74705SXin Li if (FilesSet.insert(Filename).second)
313*67e74705SXin Li Files.push_back(Filename);
314*67e74705SXin Li }
315*67e74705SXin Li
316*67e74705SXin Li /// Print the filename, with escaping or quoting that accommodates the three
317*67e74705SXin Li /// most likely tools that use dependency files: GNU Make, BSD Make, and
318*67e74705SXin Li /// NMake/Jom.
319*67e74705SXin Li ///
320*67e74705SXin Li /// BSD Make is the simplest case: It does no escaping at all. This means
321*67e74705SXin Li /// characters that are normally delimiters, i.e. space and # (the comment
322*67e74705SXin Li /// character) simply aren't supported in filenames.
323*67e74705SXin Li ///
324*67e74705SXin Li /// GNU Make does allow space and # in filenames, but to avoid being treated
325*67e74705SXin Li /// as a delimiter or comment, these must be escaped with a backslash. Because
326*67e74705SXin Li /// backslash is itself the escape character, if a backslash appears in a
327*67e74705SXin Li /// filename, it should be escaped as well. (As a special case, $ is escaped
328*67e74705SXin Li /// as $$, which is the normal Make way to handle the $ character.)
329*67e74705SXin Li /// For compatibility with BSD Make and historical practice, if GNU Make
330*67e74705SXin Li /// un-escapes characters in a filename but doesn't find a match, it will
331*67e74705SXin Li /// retry with the unmodified original string.
332*67e74705SXin Li ///
333*67e74705SXin Li /// GCC tries to accommodate both Make formats by escaping any space or #
334*67e74705SXin Li /// characters in the original filename, but not escaping backslashes. The
335*67e74705SXin Li /// apparent intent is so that filenames with backslashes will be handled
336*67e74705SXin Li /// correctly by BSD Make, and by GNU Make in its fallback mode of using the
337*67e74705SXin Li /// unmodified original string; filenames with # or space characters aren't
338*67e74705SXin Li /// supported by BSD Make at all, but will be handled correctly by GNU Make
339*67e74705SXin Li /// due to the escaping.
340*67e74705SXin Li ///
341*67e74705SXin Li /// A corner case that GCC gets only partly right is when the original filename
342*67e74705SXin Li /// has a backslash immediately followed by space or #. GNU Make would expect
343*67e74705SXin Li /// this backslash to be escaped; however GCC escapes the original backslash
344*67e74705SXin Li /// only when followed by space, not #. It will therefore take a dependency
345*67e74705SXin Li /// from a directive such as
346*67e74705SXin Li /// #include "a\ b\#c.h"
347*67e74705SXin Li /// and emit it as
348*67e74705SXin Li /// a\\\ b\\#c.h
349*67e74705SXin Li /// which GNU Make will interpret as
350*67e74705SXin Li /// a\ b\
351*67e74705SXin Li /// followed by a comment. Failing to find this file, it will fall back to the
352*67e74705SXin Li /// original string, which probably doesn't exist either; in any case it won't
353*67e74705SXin Li /// find
354*67e74705SXin Li /// a\ b\#c.h
355*67e74705SXin Li /// which is the actual filename specified by the include directive.
356*67e74705SXin Li ///
357*67e74705SXin Li /// Clang does what GCC does, rather than what GNU Make expects.
358*67e74705SXin Li ///
359*67e74705SXin Li /// NMake/Jom has a different set of scary characters, but wraps filespecs in
360*67e74705SXin Li /// double-quotes to avoid misinterpreting them; see
361*67e74705SXin Li /// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info,
362*67e74705SXin Li /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
363*67e74705SXin Li /// for Windows file-naming info.
PrintFilename(raw_ostream & OS,StringRef Filename,DependencyOutputFormat OutputFormat)364*67e74705SXin Li static void PrintFilename(raw_ostream &OS, StringRef Filename,
365*67e74705SXin Li DependencyOutputFormat OutputFormat) {
366*67e74705SXin Li if (OutputFormat == DependencyOutputFormat::NMake) {
367*67e74705SXin Li // Add quotes if needed. These are the characters listed as "special" to
368*67e74705SXin Li // NMake, that are legal in a Windows filespec, and that could cause
369*67e74705SXin Li // misinterpretation of the dependency string.
370*67e74705SXin Li if (Filename.find_first_of(" #${}^!") != StringRef::npos)
371*67e74705SXin Li OS << '\"' << Filename << '\"';
372*67e74705SXin Li else
373*67e74705SXin Li OS << Filename;
374*67e74705SXin Li return;
375*67e74705SXin Li }
376*67e74705SXin Li assert(OutputFormat == DependencyOutputFormat::Make);
377*67e74705SXin Li for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
378*67e74705SXin Li if (Filename[i] == '#') // Handle '#' the broken gcc way.
379*67e74705SXin Li OS << '\\';
380*67e74705SXin Li else if (Filename[i] == ' ') { // Handle space correctly.
381*67e74705SXin Li OS << '\\';
382*67e74705SXin Li unsigned j = i;
383*67e74705SXin Li while (j > 0 && Filename[--j] == '\\')
384*67e74705SXin Li OS << '\\';
385*67e74705SXin Li } else if (Filename[i] == '$') // $ is escaped by $$.
386*67e74705SXin Li OS << '$';
387*67e74705SXin Li OS << Filename[i];
388*67e74705SXin Li }
389*67e74705SXin Li }
390*67e74705SXin Li
OutputDependencyFile()391*67e74705SXin Li void DFGImpl::OutputDependencyFile() {
392*67e74705SXin Li if (SeenMissingHeader) {
393*67e74705SXin Li llvm::sys::fs::remove(OutputFile);
394*67e74705SXin Li return;
395*67e74705SXin Li }
396*67e74705SXin Li
397*67e74705SXin Li std::error_code EC;
398*67e74705SXin Li llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
399*67e74705SXin Li if (EC) {
400*67e74705SXin Li PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
401*67e74705SXin Li << EC.message();
402*67e74705SXin Li return;
403*67e74705SXin Li }
404*67e74705SXin Li
405*67e74705SXin Li // Write out the dependency targets, trying to avoid overly long
406*67e74705SXin Li // lines when possible. We try our best to emit exactly the same
407*67e74705SXin Li // dependency file as GCC (4.2), assuming the included files are the
408*67e74705SXin Li // same.
409*67e74705SXin Li const unsigned MaxColumns = 75;
410*67e74705SXin Li unsigned Columns = 0;
411*67e74705SXin Li
412*67e74705SXin Li for (std::vector<std::string>::iterator
413*67e74705SXin Li I = Targets.begin(), E = Targets.end(); I != E; ++I) {
414*67e74705SXin Li unsigned N = I->length();
415*67e74705SXin Li if (Columns == 0) {
416*67e74705SXin Li Columns += N;
417*67e74705SXin Li } else if (Columns + N + 2 > MaxColumns) {
418*67e74705SXin Li Columns = N + 2;
419*67e74705SXin Li OS << " \\\n ";
420*67e74705SXin Li } else {
421*67e74705SXin Li Columns += N + 1;
422*67e74705SXin Li OS << ' ';
423*67e74705SXin Li }
424*67e74705SXin Li // Targets already quoted as needed.
425*67e74705SXin Li OS << *I;
426*67e74705SXin Li }
427*67e74705SXin Li
428*67e74705SXin Li OS << ':';
429*67e74705SXin Li Columns += 1;
430*67e74705SXin Li
431*67e74705SXin Li // Now add each dependency in the order it was seen, but avoiding
432*67e74705SXin Li // duplicates.
433*67e74705SXin Li for (std::vector<std::string>::iterator I = Files.begin(),
434*67e74705SXin Li E = Files.end(); I != E; ++I) {
435*67e74705SXin Li // Start a new line if this would exceed the column limit. Make
436*67e74705SXin Li // sure to leave space for a trailing " \" in case we need to
437*67e74705SXin Li // break the line on the next iteration.
438*67e74705SXin Li unsigned N = I->length();
439*67e74705SXin Li if (Columns + (N + 1) + 2 > MaxColumns) {
440*67e74705SXin Li OS << " \\\n ";
441*67e74705SXin Li Columns = 2;
442*67e74705SXin Li }
443*67e74705SXin Li OS << ' ';
444*67e74705SXin Li PrintFilename(OS, *I, OutputFormat);
445*67e74705SXin Li Columns += N + 1;
446*67e74705SXin Li }
447*67e74705SXin Li OS << '\n';
448*67e74705SXin Li
449*67e74705SXin Li // Create phony targets if requested.
450*67e74705SXin Li if (PhonyTarget && !Files.empty()) {
451*67e74705SXin Li // Skip the first entry, this is always the input file itself.
452*67e74705SXin Li for (std::vector<std::string>::iterator I = Files.begin() + 1,
453*67e74705SXin Li E = Files.end(); I != E; ++I) {
454*67e74705SXin Li OS << '\n';
455*67e74705SXin Li PrintFilename(OS, *I, OutputFormat);
456*67e74705SXin Li OS << ":\n";
457*67e74705SXin Li }
458*67e74705SXin Li }
459*67e74705SXin Li }
460*67e74705SXin Li
visitInputFile(llvm::StringRef Filename,bool IsSystem,bool IsOverridden,bool IsExplicitModule)461*67e74705SXin Li bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
462*67e74705SXin Li bool IsSystem, bool IsOverridden,
463*67e74705SXin Li bool IsExplicitModule) {
464*67e74705SXin Li assert(!IsSystem || needsSystemInputFileVisitation());
465*67e74705SXin Li if (IsOverridden || IsExplicitModule)
466*67e74705SXin Li return true;
467*67e74705SXin Li
468*67e74705SXin Li Parent.AddFilename(Filename);
469*67e74705SXin Li return true;
470*67e74705SXin Li }
471*67e74705SXin Li
visitModuleFile(llvm::StringRef Filename,serialization::ModuleKind Kind)472*67e74705SXin Li void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename,
473*67e74705SXin Li serialization::ModuleKind Kind) {
474*67e74705SXin Li if (Parent.includeModuleFiles())
475*67e74705SXin Li Parent.AddFilename(Filename);
476*67e74705SXin Li }
477