1750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//===--- DependencyFile.cpp - Generate dependency file --------------------===//
2750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//
3750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//                     The LLVM Compiler Infrastructure
4750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//
5750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar// This file is distributed under the University of Illinois Open Source
6750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar// License. See LICENSE.TXT for details.
7750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//
8750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//===----------------------------------------------------------------------===//
9750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//
10750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar// This code generates dependency files.
11750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//
12750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar//===----------------------------------------------------------------------===//
13750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
14b09f6e15c59b89d5820db8ef40598eb1d1323c1fEli Friedman#include "clang/Frontend/Utils.h"
15b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner#include "clang/Basic/FileManager.h"
160e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Basic/SourceManager.h"
170e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Frontend/DependencyOutputOptions.h"
180e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Frontend/FrontendDiagnostic.h"
190e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Lex/DirectoryLookup.h"
20bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne#include "clang/Lex/LexDiagnostic.h"
210e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Lex/PPCallbacks.h"
220e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar#include "clang/Lex/Preprocessor.h"
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Serialization/ASTReader.h"
24750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar#include "llvm/ADT/StringSet.h"
250b214905f7fff7fa21ecc54a17b97372ba0c9a07Benjamin Kramer#include "llvm/Support/FileSystem.h"
26a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman#include "llvm/Support/Path.h"
277e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar#include "llvm/Support/raw_ostream.h"
28750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
29750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbarusing namespace clang;
30750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
31750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbarnamespace {
32ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct DepCollectorPPCallbacks : public PPCallbacks {
33ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  DependencyCollector &DepCollector;
34ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  SourceManager &SM;
35ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM)
36ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      : DepCollector(L), SM(SM) { }
37ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
38ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
39ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                   SrcMgr::CharacteristicKind FileType,
40ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                   FileID PrevFID) override {
41ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (Reason != PPCallbacks::EnterFile)
42ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return;
43ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
44ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    // Dependency generation really does want to go all the way to the
45ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    // file entry for a source location to find out what is depended on.
46ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    // We do not want #line markers to affect dependency generation!
47ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    const FileEntry *FE =
48ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
49ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (!FE)
50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return;
51ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
52ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    StringRef Filename = FE->getName();
53ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
54ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    // Remove leading "./" (or ".//" or "././" etc.)
55ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    while (Filename.size() > 2 && Filename[0] == '.' &&
56ef8225444452a1486bd721f3285301fe84643b00Stephen Hines           llvm::sys::path::is_separator(Filename[1])) {
57ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      Filename = Filename.substr(1);
58ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      while (llvm::sys::path::is_separator(Filename[0]))
59ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        Filename = Filename.substr(1);
60ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
61ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
62ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
63ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                   FileType != SrcMgr::C_User,
64ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                   /*IsModuleFile*/false, /*IsMissing*/false);
65ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
66ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
67ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
68ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                          StringRef FileName, bool IsAngled,
69ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                          CharSourceRange FilenameRange, const FileEntry *File,
70ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                          StringRef SearchPath, StringRef RelativePath,
71ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                          const Module *Imported) override {
72ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (!File)
73ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      DepCollector.maybeAddDependency(FileName, /*FromModule*/false,
74ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                     /*IsSystem*/false, /*IsModuleFile*/false,
75ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                     /*IsMissing*/true);
76ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    // Files that actually exist are handled by FileChanged.
77ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
78ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
79ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void EndOfMainFile() override {
80ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    DepCollector.finishedMainFile();
81ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
82ef8225444452a1486bd721f3285301fe84643b00Stephen Hines};
83ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
84ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct DepCollectorASTListener : public ASTReaderListener {
85ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  DependencyCollector &DepCollector;
86ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
87ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  bool needsInputFileVisitation() override { return true; }
88ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  bool needsSystemInputFileVisitation() override {
89ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return DepCollector.needSystemDependencies();
90ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
91ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void visitModuleFile(StringRef Filename) override {
92ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
93ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                   /*IsSystem*/false, /*IsModuleFile*/true,
94ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                   /*IsMissing*/false);
95ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
96ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  bool visitInputFile(StringRef Filename, bool IsSystem,
97ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                      bool IsOverridden) override {
98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (IsOverridden)
99ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return true;
100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                   /*IsModuleFile*/false, /*IsMissing*/false);
103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return true;
104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
105ef8225444452a1486bd721f3285301fe84643b00Stephen Hines};
106ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} // end anonymous namespace
107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
108ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                            bool IsSystem, bool IsModuleFile,
110ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                            bool IsMissing) {
111ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  if (Seen.insert(Filename) &&
112ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Dependencies.push_back(Filename);
114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}
115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
116ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesbool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
117ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                       bool IsSystem, bool IsModuleFile,
118ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                       bool IsMissing) {
119ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  return Filename != "<built-in>" && (needSystemDependencies() || !IsSystem);
120ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}
121ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
122ef8225444452a1486bd721f3285301fe84643b00Stephen HinesDependencyCollector::~DependencyCollector() { }
123ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
124ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  PP.addPPCallbacks(new DepCollectorPPCallbacks(*this, PP.getSourceManager()));
125ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}
126ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid DependencyCollector::attachToASTReader(ASTReader &R) {
127ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R.addListener(new DepCollectorASTListener(*this));
128ef8225444452a1486bd721f3285301fe84643b00Stephen Hines}
129ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
130ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesnamespace {
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// Private implementation for DependencyFileGenerator
132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass DFGImpl : public PPCallbacks {
1337e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  std::vector<std::string> Files;
1347e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  llvm::StringSet<> FilesSet;
135750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar  const Preprocessor *PP;
1361b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  std::string OutputFile;
13702fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner  std::vector<std::string> Targets;
138b5c8f8bddc6007b154b5c40640c4f80e7cb0a6ebEli Friedman  bool IncludeSystemHeaders;
139b5c8f8bddc6007b154b5c40640c4f80e7cb0a6ebEli Friedman  bool PhonyTarget;
140bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne  bool AddMissingHeaderDeps;
1411b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  bool SeenMissingHeader;
142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool IncludeModuleFiles;
143750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbarprivate:
144750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar  bool FileMatchesDepCriteria(const char *Filename,
1459d72851fec9e9c62570a027d42701562bbf29751Chris Lattner                              SrcMgr::CharacteristicKind FileType);
146750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar  void OutputDependencyFile();
147750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
148750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbarpublic:
149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts)
1501b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets),
1510e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar      IncludeSystemHeaders(Opts.IncludeSystemHeaders),
152bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne      PhonyTarget(Opts.UsePhonyTargets),
1531b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      SeenMissingHeader(false),
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      IncludeModuleFiles(Opts.IncludeModuleFiles) {}
156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   SrcMgr::CharacteristicKind FileType,
159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   FileID PrevFID) override;
160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef FileName, bool IsAngled,
162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          CharSourceRange FilenameRange, const FileEntry *File,
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef SearchPath, StringRef RelativePath,
164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          const Module *Imported) override;
165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void EndOfMainFile() override {
167a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar    OutputDependencyFile();
168a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  }
169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void AddFilename(StringRef Filename);
171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool includeSystemHeaders() const { return IncludeSystemHeaders; }
172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool includeModuleFiles() const { return IncludeModuleFiles; }
173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass DFGASTReaderListener : public ASTReaderListener {
176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DFGImpl &Parent;
177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DFGASTReaderListener(DFGImpl &Parent)
179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  : Parent(Parent) { }
180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool needsInputFileVisitation() override { return true; }
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool needsSystemInputFileVisitation() override {
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return Parent.includeSystemHeaders();
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void visitModuleFile(StringRef Filename) override;
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool visitInputFile(StringRef Filename, bool isSystem,
186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                      bool isOverridden) override;
187750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar};
188750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar}
189750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
190651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesDependencyFileGenerator::DependencyFileGenerator(void *Impl)
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines: Impl(Impl) { }
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
193651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesDependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) {
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1960e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar  if (Opts.Targets.empty()) {
197ca11f61233b2acc266f371816e48290af4e10528Daniel Dunbar    PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
1986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
1990e0bae8139e25de81f18b6a519783a06f7ba1e25Daniel Dunbar  }
200750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
201bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne  // Disable the "file not found" diagnostic if the -MG option was given.
202f84139a1331c63c998e8b7d54148c75ac0b48ccdEli Friedman  if (Opts.AddMissingHeaderDeps)
203f84139a1331c63c998e8b7d54148c75ac0b48ccdEli Friedman    PP.SetSuppressIncludeNotFoundError(true);
204bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DFGImpl *Callback = new DFGImpl(&PP, Opts);
206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  PP.addPPCallbacks(Callback); // PP owns the Callback
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return new DependencyFileGenerator(Callback);
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(I && "missing implementation");
213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  R.addListener(new DFGASTReaderListener(*I));
214750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar}
215750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
216750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar/// FileMatchesDepCriteria - Determine whether the given Filename should be
217750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar/// considered as a dependency.
218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool DFGImpl::FileMatchesDepCriteria(const char *Filename,
219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                     SrcMgr::CharacteristicKind FileType) {
220a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  if (strcmp("<built-in>", Filename) == 0)
221a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar    return false;
222a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar
223b5c8f8bddc6007b154b5c40640c4f80e7cb0a6ebEli Friedman  if (IncludeSystemHeaders)
224a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar    return true;
225750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
226a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  return FileType == SrcMgr::C_User;
227750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar}
228750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DFGImpl::FileChanged(SourceLocation Loc,
230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          FileChangeReason Reason,
231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          SrcMgr::CharacteristicKind FileType,
232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          FileID PrevFID) {
233750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar  if (Reason != PPCallbacks::EnterFile)
234750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar    return;
2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
236a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  // Dependency generation really does want to go all the way to the
237a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  // file entry for a source location to find out what is depended on.
238a5a7bd0de7b6b80212095195a055a4a43f21d4b2Daniel Dunbar  // We do not want #line markers to affect dependency generation!
239b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  SourceManager &SM = PP->getSourceManager();
2401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
241e86e4cd097f50ca1c0bfde9142e0460d0d1203dbChris Lattner  const FileEntry *FE =
242402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth    SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc)));
2436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!FE) return;
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef Filename = FE->getName();
246a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman  if (!FileMatchesDepCriteria(Filename.data(), FileType))
247750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar    return;
248750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
249a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman  // Remove leading "./" (or ".//" or "././" etc.)
250a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman  while (Filename.size() > 2 && Filename[0] == '.' &&
251a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman         llvm::sys::path::is_separator(Filename[1])) {
252a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman    Filename = Filename.substr(1);
253a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman    while (llvm::sys::path::is_separator(Filename[0]))
254a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman      Filename = Filename.substr(1);
255a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman  }
256a6e023c4491a8a8116c11783f4e81c7bd172f88dEli Friedman
257bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne  AddFilename(Filename);
258bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne}
259bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne
260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DFGImpl::InclusionDirective(SourceLocation HashLoc,
261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 const Token &IncludeTok,
262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 StringRef FileName,
263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 bool IsAngled,
264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 CharSourceRange FilenameRange,
265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 const FileEntry *File,
266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 StringRef SearchPath,
267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 StringRef RelativePath,
268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                 const Module *Imported) {
2691b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  if (!File) {
2701b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    if (AddMissingHeaderDeps)
2711b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      AddFilename(FileName);
2721b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    else
2731b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      SeenMissingHeader = true;
2741b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  }
275bb52786da8d055568eef6e5694288c1258bc8c2aPeter Collingbourne}
276750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DFGImpl::AddFilename(StringRef Filename) {
2787e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  if (FilesSet.insert(Filename))
2797e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    Files.push_back(Filename);
280750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar}
281750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
282ddc15c40d22718d7b7060634b782d1a3ce9184a8Benjamin Kramer/// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
283ddc15c40d22718d7b7060634b782d1a3ce9184a8Benjamin Kramer/// other scary characters.
2845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void PrintFilename(raw_ostream &OS, StringRef Filename) {
2859d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner  for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
286ddc15c40d22718d7b7060634b782d1a3ce9184a8Benjamin Kramer    if (Filename[i] == ' ' || Filename[i] == '#')
2879d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner      OS << '\\';
288ddc15c40d22718d7b7060634b782d1a3ce9184a8Benjamin Kramer    else if (Filename[i] == '$') // $ is escaped by $$.
289ddc15c40d22718d7b7060634b782d1a3ce9184a8Benjamin Kramer      OS << '$';
2909d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner    OS << Filename[i];
2919d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner  }
2929d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner}
2939d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner
294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DFGImpl::OutputDependencyFile() {
2951b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  if (SeenMissingHeader) {
296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    llvm::sys::fs::remove(OutputFile);
2971b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    return;
2981b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  }
2991b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne
3001b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  std::string Err;
301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::raw_fd_ostream OS(OutputFile.c_str(), Err, llvm::sys::fs::F_Text);
3021b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  if (!Err.empty()) {
3031b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    PP->getDiagnostics().Report(diag::err_fe_error_opening)
3041b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      << OutputFile << Err;
3051b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    return;
3061b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  }
3071b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne
3087e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // Write out the dependency targets, trying to avoid overly long
3097e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // lines when possible. We try our best to emit exactly the same
3107e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // dependency file as GCC (4.2), assuming the included files are the
3117e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // same.
3127e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  const unsigned MaxColumns = 75;
31302fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner  unsigned Columns = 0;
31402fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner
31502fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner  for (std::vector<std::string>::iterator
31602fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner         I = Targets.begin(), E = Targets.end(); I != E; ++I) {
31702fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner    unsigned N = I->length();
31802fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner    if (Columns == 0) {
31902fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner      Columns += N;
32002fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner    } else if (Columns + N + 2 > MaxColumns) {
32102fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner      Columns = N + 2;
3221b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      OS << " \\\n  ";
32302fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner    } else {
32402fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner      Columns += N + 1;
3251b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      OS << ' ';
32602fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner    }
3279d50634cfc268ecc9a7250226dd5ca0e945240d4Chris Lattner    // Targets already quoted as needed.
3281b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    OS << *I;
32902fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner  }
33002fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner
3311b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  OS << ':';
33202fbb2578538e93f901f75fdc7d278c4c0e935deChris Lattner  Columns += 1;
3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3347e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // Now add each dependency in the order it was seen, but avoiding
3357e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // duplicates.
3367e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  for (std::vector<std::string>::iterator I = Files.begin(),
3377e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar         E = Files.end(); I != E; ++I) {
3387e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    // Start a new line if this would exceed the column limit. Make
3397e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    // sure to leave space for a trailing " \" in case we need to
3407e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    // break the line on the next iteration.
3417e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    unsigned N = I->length();
3427e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    if (Columns + (N + 1) + 2 > MaxColumns) {
3431b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      OS << " \\\n ";
3447e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar      Columns = 2;
3457e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    }
3461b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    OS << ' ';
3471b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne    PrintFilename(OS, *I);
3487e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    Columns += N + 1;
3497e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  }
3501b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne  OS << '\n';
3517e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar
3527e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar  // Create phony targets if requested.
353ccad3db9b95012e260c71ded41c6141619202b09Fariborz Jahanian  if (PhonyTarget && !Files.empty()) {
3547e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    // Skip the first entry, this is always the input file itself.
3557e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    for (std::vector<std::string>::iterator I = Files.begin() + 1,
3567e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar           E = Files.end(); I != E; ++I) {
3571b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      OS << '\n';
3581b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      PrintFilename(OS, *I);
3591b91ab467cffd44c222f1c5bed76910cce059a9ePeter Collingbourne      OS << ":\n";
3607e9f1f7de84e6876e581980ec122d688fcfe1f31Daniel Dunbar    }
361750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar  }
362750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar}
363750c358049a0e91fd71a8d10a9ac8299c943e238Daniel Dunbar
364651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                          bool IsSystem, bool IsOverridden) {
366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(!IsSystem || needsSystemInputFileVisitation());
367651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (IsOverridden)
368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Parent.AddFilename(Filename);
371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return true;
372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename) {
375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Parent.includeModuleFiles())
376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Parent.AddFilename(Filename);
377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
378