clang: lib/Frontend/DependencyFile.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/ADT/StringSet.h"

24#include "llvm/Support/FileSystem.h"

25#include "llvm/Support/Path.h"

26#include "llvm/Support/raw_ostream.h"

27#include

28

29using namespace clang;

30

31namespace {

32struct DepCollectorPPCallbacks : public PPCallbacks {

36 : DepCollector(L), PP(PP) {}

37

41 if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)

42 return;

43

44

45

46

47 if (std::optional Filename =

50 llvm::sys::path::remove_leading_dotslash(*Filename),

51 false, isSystem(FileType), false,

52 false);

53 }

54

58 llvm::sys::path::remove_leading_dotslash(SkippedFile.getName());

61 false,

62 false);

63 }

64

68 assert(File && "expected to only be called when the file is found");

70 llvm::sys::path::remove_leading_dotslash(File->getName());

72 false,

73 false,

74 false,

75 false);

76 }

77

79 StringRef FileName, bool IsAngled,

82 StringRef RelativePath, const Module *SuggestedModule,

83 bool ModuleImported,

87 false,

88 false,

89 true);

90

91 }

92

96 return;

98 llvm::sys::path::remove_leading_dotslash(File->getName());

100 false, false,

101 false,

102 false);

103 }

104

109 return;

111 llvm::sys::path::remove_leading_dotslash(File->getName());

114 false,

115 false);

116 }

117

120 }

121};

122

126

128 bool IsSystem) override {

131 IsSystem,

132 false,

133 false);

134 }

135};

136

141 : DepCollector(L), FileMgr(FileMgr) {}

145 }

149 false, true,

150 false);

151 }

153 bool IsOverridden, bool IsExplicitModule) override {

154 if (IsOverridden || IsExplicitModule)

155 return true;

156

157

158

161

163 false,

164 false);

165 return true;

166 }

167};

168}

169

171 bool FromModule, bool IsSystem,

172 bool IsModuleFile,

173 bool IsMissing) {

176}

177

179 StringRef SearchPath;

180#ifdef _WIN32

181

183 llvm::sys::path::native(TmpPath);

184 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);

185 SearchPath = TmpPath.str();

186#else

188#endif

189

190 if (Seen.insert(SearchPath).second) {

191 Dependencies.push_back(std::string(Filename));

192 return true;

193 }

194 return false;

195}

196

198 return Filename == "";

199}

200

202 bool IsSystem, bool IsModuleFile,

203 bool IsMissing) {

206}

207

210 PP.addPPCallbacks(std::make_unique(*this, PP));

212 std::make_unique(*this));

213}

216 std::make_unique(*this, R.getFileManager()));

217}

218

221 : OutputFile(Opts.OutputFile), Targets(Opts.Targets),

222 IncludeSystemHeaders(Opts.IncludeSystemHeaders),

223 PhonyTarget(Opts.UsePhonyTargets),

224 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false),

225 IncludeModuleFiles(Opts.IncludeModuleFiles),

226 OutputFormat(Opts.OutputFormat), InputFileIndex(0) {

227 for (const auto &ExtraDep : Opts.ExtraDeps) {

229 ++InputFileIndex;

230 }

231}

232

234

235 if (AddMissingHeaderDeps)

237

239}

240

242 bool IsSystem, bool IsModuleFile,

243 bool IsMissing) {

244 if (IsMissing) {

245

246 if (AddMissingHeaderDeps)

247 return true;

248 SeenMissingHeader = true;

249 return false;

250 }

251 if (IsModuleFile && !IncludeModuleFiles)

252 return false;

253

255 return false;

256

257 if (IncludeSystemHeaders)

258 return true;

259

260 return !IsSystem;

261}

262

265}

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

317

319 llvm::sys::path::native(Filename.str(), NativePath);

320

322

323

324

325 if (NativePath.find_first_of(" #${}^!") != StringRef::npos)

326 OS << '\"' << NativePath << '\"';

327 else

328 OS << NativePath;

329 return;

330 }

332 for (unsigned i = 0, e = NativePath.size(); i != e; ++i) {

333 if (NativePath[i] == '#')

334 OS << '\\';

335 else if (NativePath[i] == ' ') {

336 OS << '\\';

337 unsigned j = i;

338 while (j > 0 && NativePath[--j] == '\\')

339 OS << '\\';

340 } else if (NativePath[i] == '$')

341 OS << '$';

342 OS << NativePath[i];

343 }

344}

345

347 if (SeenMissingHeader) {

348 llvm::sys::fs::remove(OutputFile);

349 return;

350 }

351

352 std::error_code EC;

353 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);

354 if (EC) {

355 Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message();

356 return;

357 }

358

360}

361

363

364

365

366

367 const unsigned MaxColumns = 75;

368 unsigned Columns = 0;

369

370 for (StringRef Target : Targets) {

371 unsigned N = Target.size();

372 if (Columns == 0) {

373 Columns += N;

374 } else if (Columns + N + 2 > MaxColumns) {

375 Columns = N + 2;

376 OS << " \\\n ";

377 } else {

378 Columns += N + 1;

379 OS << ' ';

380 }

381

383 }

384

385 OS << ':';

386 Columns += 1;

387

388

389

391 for (StringRef File : Files) {

392 if (File == "")

393 continue;

394

395

396

397 unsigned N = File.size();

398 if (Columns + (N + 1) + 2 > MaxColumns) {

399 OS << " \\\n ";

400 Columns = 2;

401 }

402 OS << ' ';

404 Columns += N + 1;

405 }

406 OS << '\n';

407

408

409 if (PhonyTarget && !Files.empty()) {

410 unsigned Index = 0;

411 for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {

412 if (Index++ == InputFileIndex)

413 continue;

415 OS << ":\n";

416 }

417 }

418}

static void PrintFilename(raw_ostream &OS, StringRef Filename, DependencyOutputFormat OutputFormat)

Print the filename, with escaping or quoting that accommodates the three most likely tools that use d...

static bool isSpecialFilename(StringRef Filename)

Defines the clang::FileManager interface and associated types.

llvm::MachO::FileType FileType

llvm::MachO::Target Target

Defines the PPCallbacks interface.

Defines the clang::Preprocessor interface.

Defines the SourceManager interface.

Abstract interface for callback invocations by the ASTReader.

virtual bool needsInputFileVisitation()

Returns true if this ASTReaderListener wants to receive the input files of the AST file via visitInpu...

virtual bool visitInputFile(StringRef Filename, bool isSystem, bool isOverridden, bool isExplicitModule)

if needsInputFileVisitation returns true, this is called for each non-system input file of the AST Fi...

virtual void visitModuleFile(StringRef Filename, serialization::ModuleKind Kind)

This is called for each AST file loaded.

virtual bool needsSystemInputFileVisitation()

Returns true if this ASTReaderListener wants to receive the system input files of the AST file via vi...

Reads an AST files chain containing the contents of a translation unit.

void addListener(std::unique_ptr< ASTReaderListener > L)

Add an AST callback listener.

FileManager & getFileManager() const

Represents a character-granular source range.

An interface for collecting the dependencies of a compilation.

virtual void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)

Add a dependency Filename if it has not been seen before and sawDependency() returns true.

bool addDependency(StringRef Filename)

Return true if the filename was added to the list of dependencies, false otherwise.

virtual void attachToPreprocessor(Preprocessor &PP)

ArrayRef< std::string > getDependencies() const

virtual void finishedMainFile(DiagnosticsEngine &Diags)

Called when the end of the main file is reached.

virtual void attachToASTReader(ASTReader &R)

virtual ~DependencyCollector()

virtual bool needSystemDependencies()

Return true if system files should be passed to sawDependency().

virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)

Called when a new file is seen.

void outputDependencyFile(llvm::raw_ostream &OS)

void attachToPreprocessor(Preprocessor &PP) override

void finishedMainFile(DiagnosticsEngine &Diags) override

Called when the end of the main file is reached.

bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) final

Called when a new file is seen.

DependencyFileGenerator(const DependencyOutputOptions &Opts)

DependencyOutputOptions - Options for controlling the compiler dependency file generation.

std::vector< std::pair< std::string, ExtraDepKind > > ExtraDeps

A list of extra dependencies (filename and kind) to be used for every target.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...

StringRef getName() const

The name of this FileEntry.

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

Implements support for file system lookup, file system caching, and directory search management.

OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)

Get a FileEntryRef if it exists, without doing anything on error.

Record the location of an inclusion directive, such as an #include or #import statement.

A mechanism to observe the actions of the module map parser as it reads module map files.

virtual void moduleMapFileRead(SourceLocation FileStart, FileEntryRef File, bool IsSystem)

Called when a module map file has been read.

void addModuleMapCallbacks(std::unique_ptr< ModuleMapCallbacks > Callback)

Add a module map callback.

Describes a module or submodule.

This interface provides a way to observe the actions of the preprocessor as it does its thing.

virtual void HasEmbed(SourceLocation Loc, StringRef FileName, bool IsAngled, OptionalFileEntryRef File)

Hook called when a '__has_embed' directive is read.

virtual void EndOfMainFile()

Callback invoked when the end of the main file is reached.

virtual void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, SrcMgr::CharacteristicKind FileType)

Callback invoked whenever a source file is skipped as the result of header guard optimization.

virtual void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled, OptionalFileEntryRef File, const LexEmbedParametersResult &Params)

Callback invoked whenever an embed directive has been processed, regardless of whether the embed will...

virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled, OptionalFileEntryRef File, SrcMgr::CharacteristicKind FileType)

Hook called when a '__has_include' or '__has_include_next' directive is read.

virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc)

Callback invoked whenever the Lexer moves to a different file for lexing.

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

void addPPCallbacks(std::unique_ptr< PPCallbacks > C)

SourceManager & getSourceManager() const

HeaderSearch & getHeaderSearchInfo() const

void SetSuppressIncludeNotFoundError(bool Suppress)

DiagnosticsEngine & getDiagnostics() const

Encodes a location in the source.

std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const

Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...

Token - This structure provides full information about a lexed token.

CharacteristicKind

Indicates whether a file or directory holds normal user code, system code, or system code which is im...

bool isSystem(CharacteristicKind CK)

Determine whether a file / directory characteristic is for system code.

ModuleKind

Specifies the kind of module that has been loaded.

The JSON file list parser is used to communicate input to InstallAPI.

DependencyOutputFormat

DependencyOutputFormat - Format for the compiler dependency file.