clang 24.0.0git
InclusionRewriter.cpp
Go to the documentation of this file.
1//===--- InclusionRewriter.cpp - Rewrite includes into their expansions ---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This code rewrites include invocations into their expansions. This gives you
10// a file with all included files merged into it.
11//
12//===----------------------------------------------------------------------===//
13
17#include "clang/Lex/Pragma.h"
19#include "llvm/ADT/SmallString.h"
20#include "llvm/Support/raw_ostream.h"
21#include <optional>
22
23using namespace clang;
24using namespace llvm;
25
26namespace {
27
28class InclusionRewriter : public PPCallbacks {
29 /// Information about which #includes were actually performed,
30 /// created by preprocessor callbacks.
31 struct IncludedFile {
32 FileID Id;
34 IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType)
35 : Id(Id), FileType(FileType) {}
36 };
37 Preprocessor &PP; ///< Used to find inclusion directives.
38 SourceManager &SM; ///< Used to read and manage source files.
39 raw_ostream &OS; ///< The destination stream for rewritten contents.
40 StringRef MainEOL; ///< The line ending marker to use.
41 llvm::MemoryBufferRef PredefinesBuffer; ///< The preprocessor predefines.
42 bool ShowLineMarkers; ///< Show #line markers.
43 bool UseLineDirectives; ///< Use of line directives or line markers.
44 /// Tracks where inclusions that change the file are found.
45 std::map<SourceLocation, IncludedFile> FileIncludes;
46 /// Tracks where inclusions that import modules are found.
47 std::map<SourceLocation, const Module *> ModuleIncludes;
48 /// Tracks where inclusions that enter modules (in a module build) are found.
49 std::map<SourceLocation, const Module *> ModuleEntryIncludes;
50 /// Tracks where #if and #elif directives get evaluated and whether to true.
51 std::map<SourceLocation, bool> IfConditions;
52 /// Used transitively for building up the FileIncludes mapping over the
53 /// various \c PPCallbacks callbacks.
54 SourceLocation LastInclusionLocation;
55public:
56 InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers,
57 bool UseLineDirectives);
58 void Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
59 void setPredefinesBuffer(const llvm::MemoryBufferRef &Buf) {
60 PredefinesBuffer = Buf;
61 }
62 void detectMainFileEOL();
63 void handleModuleBegin(Token &Tok) {
64 assert(Tok.getKind() == tok::annot_module_begin);
65 ModuleEntryIncludes.insert(
67 }
68private:
69 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
71 FileID PrevFID) override;
72 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
74 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
75 StringRef FileName, bool IsAngled,
76 CharSourceRange FilenameRange,
77 OptionalFileEntryRef File, StringRef SearchPath,
78 StringRef RelativePath, const Module *SuggestedModule,
79 bool ModuleImported,
81 void If(SourceLocation Loc, SourceRange ConditionRange,
82 ConditionValueKind ConditionValue) override;
83 void Elif(SourceLocation Loc, SourceRange ConditionRange,
84 ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
85 void WriteLineInfo(StringRef Filename, int Line,
87 StringRef Extra = StringRef());
88 void WriteImplicitModuleImport(const Module *Mod);
89 void OutputContentUpTo(const MemoryBufferRef &FromFile, unsigned &WriteFrom,
90 unsigned WriteTo, StringRef EOL, int &lines,
91 bool EnsureNewline);
92 void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken,
93 const MemoryBufferRef &FromFile, StringRef EOL,
94 unsigned &NextToWrite, int &Lines,
95 const IncludedFile *Inc = nullptr);
96 const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
97 StringRef getIncludedFileName(const IncludedFile *Inc) const;
98 const Module *FindModuleAtLocation(SourceLocation Loc) const;
99 const Module *FindEnteredModule(SourceLocation Loc) const;
100 bool IsIfAtLocationTrue(SourceLocation Loc) const;
101 StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
102};
103
104} // end anonymous namespace
105
106/// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
107InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
108 bool ShowLineMarkers,
109 bool UseLineDirectives)
110 : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
111 ShowLineMarkers(ShowLineMarkers), UseLineDirectives(UseLineDirectives),
112 LastInclusionLocation(SourceLocation()) {}
113
114/// Write appropriate line information as either #line directives or GNU line
115/// markers depending on what mode we're in, including the \p Filename and
116/// \p Line we are located at, using the specified \p EOL line separator, and
117/// any \p Extra context specifiers in GNU line directives.
118void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line,
120 StringRef Extra) {
121 if (!ShowLineMarkers)
122 return;
123 if (UseLineDirectives) {
124 OS << "#line" << ' ' << Line << ' ' << '"';
125 OS << Filename;
126 OS << '"';
127 } else {
128 // Use GNU linemarkers as described here:
129 // http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
130 OS << '#' << ' ' << Line << ' ' << '"';
131 OS << Filename;
132 OS << '"';
133 if (!Extra.empty())
134 OS << Extra;
136 // "`3' This indicates that the following text comes from a system header
137 // file, so certain warnings should be suppressed."
138 OS << " 3";
140 // as above for `3', plus "`4' This indicates that the following text
141 // should be treated as being wrapped in an implicit extern "C" block."
142 OS << " 3 4";
143 }
144 OS << MainEOL;
145}
146
147void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
148 OS << "#pragma clang module import " << Mod->getFullModuleName(true)
149 << " /* clang -frewrite-includes: implicit import */" << MainEOL;
150}
151
152/// FileChanged - Whenever the preprocessor enters or exits a #include file
153/// it invokes this handler.
154void InclusionRewriter::FileChanged(SourceLocation Loc,
155 FileChangeReason Reason,
156 SrcMgr::CharacteristicKind NewFileType,
157 FileID) {
158 if (Reason != EnterFile)
159 return;
160 if (LastInclusionLocation.isInvalid())
161 // we didn't reach this file (eg: the main file) via an inclusion directive
162 return;
163 FileID Id = FullSourceLoc(Loc, SM).getFileID();
164 auto P = FileIncludes.insert(
165 std::make_pair(LastInclusionLocation, IncludedFile(Id, NewFileType)));
166 (void)P;
167 assert(P.second && "Unexpected revisitation of the same include directive");
168 LastInclusionLocation = SourceLocation();
169}
170
171/// Called whenever an inclusion is skipped due to canonical header protection
172/// macros.
173void InclusionRewriter::FileSkipped(const FileEntryRef & /*SkippedFile*/,
174 const Token & /*FilenameTok*/,
175 SrcMgr::CharacteristicKind /*FileType*/) {
176 assert(LastInclusionLocation.isValid() &&
177 "A file, that wasn't found via an inclusion directive, was skipped");
178 LastInclusionLocation = SourceLocation();
179}
180
181/// This should be called whenever the preprocessor encounters include
182/// directives. It does not say whether the file has been included, but it
183/// provides more information about the directive (hash location instead
184/// of location inside the included file). It is assumed that the matching
185/// FileChanged() or FileSkipped() is called after this (or neither is
186/// called if this #include results in an error or does not textually include
187/// anything).
188void InclusionRewriter::InclusionDirective(
189 SourceLocation HashLoc, const Token & /*IncludeTok*/,
190 StringRef /*FileName*/, bool /*IsAngled*/,
191 CharSourceRange /*FilenameRange*/, OptionalFileEntryRef /*File*/,
192 StringRef /*SearchPath*/, StringRef /*RelativePath*/,
193 const Module *SuggestedModule, bool ModuleImported,
195 if (ModuleImported) {
196 auto P = ModuleIncludes.insert(std::make_pair(HashLoc, SuggestedModule));
197 (void)P;
198 assert(P.second && "Unexpected revisitation of the same include directive");
199 } else
200 LastInclusionLocation = HashLoc;
201}
202
203void InclusionRewriter::If(SourceLocation Loc, SourceRange ConditionRange,
204 ConditionValueKind ConditionValue) {
205 auto P = IfConditions.insert(std::make_pair(Loc, ConditionValue == CVK_True));
206 (void)P;
207 assert(P.second && "Unexpected revisitation of the same if directive");
208}
209
210void InclusionRewriter::Elif(SourceLocation Loc, SourceRange ConditionRange,
211 ConditionValueKind ConditionValue,
212 SourceLocation IfLoc) {
213 auto P = IfConditions.insert(std::make_pair(Loc, ConditionValue == CVK_True));
214 (void)P;
215 assert(P.second && "Unexpected revisitation of the same elif directive");
216}
217
218/// Simple lookup for a SourceLocation (specifically one denoting the hash in
219/// an inclusion directive) in the map of inclusion information, FileChanges.
220const InclusionRewriter::IncludedFile *
221InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const {
222 const auto I = FileIncludes.find(Loc);
223 if (I != FileIncludes.end())
224 return &I->second;
225 return nullptr;
226}
227
228/// Simple lookup for a SourceLocation (specifically one denoting the hash in
229/// an inclusion directive) in the map of module inclusion information.
230const Module *
231InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const {
232 const auto I = ModuleIncludes.find(Loc);
233 if (I != ModuleIncludes.end())
234 return I->second;
235 return nullptr;
236}
237
238/// Simple lookup for a SourceLocation (specifically one denoting the hash in
239/// an inclusion directive) in the map of module entry information.
240const Module *
241InclusionRewriter::FindEnteredModule(SourceLocation Loc) const {
242 const auto I = ModuleEntryIncludes.find(Loc);
243 if (I != ModuleEntryIncludes.end())
244 return I->second;
245 return nullptr;
246}
247
248bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const {
249 const auto I = IfConditions.find(Loc);
250 if (I != IfConditions.end())
251 return I->second;
252 return false;
253}
254
255void InclusionRewriter::detectMainFileEOL() {
256 std::optional<MemoryBufferRef> FromFile =
258 assert(FromFile);
259 if (!FromFile)
260 return; // Should never happen, but whatever.
261 MainEOL = FromFile->getBuffer().detectEOL();
262}
263
264/// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
265/// \p WriteTo - 1.
266void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile,
267 unsigned &WriteFrom, unsigned WriteTo,
268 StringRef LocalEOL, int &Line,
269 bool EnsureNewline) {
270 if (WriteTo <= WriteFrom)
271 return;
272 if (FromFile == PredefinesBuffer) {
273 // Ignore the #defines of the predefines buffer.
274 WriteFrom = WriteTo;
275 return;
276 }
277
278 // If we would output half of a line ending, advance one character to output
279 // the whole line ending. All buffers are null terminated, so looking ahead
280 // one byte is safe.
281 if (LocalEOL.size() == 2 &&
282 LocalEOL[0] == (FromFile.getBufferStart() + WriteTo)[-1] &&
283 LocalEOL[1] == (FromFile.getBufferStart() + WriteTo)[0])
284 WriteTo++;
285
286 StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom,
287 WriteTo - WriteFrom);
288 // count lines manually, it's faster than getPresumedLoc()
289 Line += TextToWrite.count(LocalEOL);
290
291 if (MainEOL == LocalEOL) {
292 OS << TextToWrite;
293 } else {
294 // Output the file one line at a time, rewriting the line endings as we go.
295 StringRef Rest = TextToWrite;
296 while (!Rest.empty()) {
297 // Identify and output the next line excluding an EOL sequence if present.
298 size_t Idx = Rest.find(LocalEOL);
299 StringRef LineText = Rest.substr(0, Idx);
300 OS << LineText;
301 if (Idx != StringRef::npos) {
302 // An EOL sequence was present, output the EOL sequence for the
303 // main source file and skip past the local EOL sequence.
304 OS << MainEOL;
305 Idx += LocalEOL.size();
306 }
307 // Strip the line just handled. If Idx is npos or matches the end of the
308 // text, Rest will be set to an empty string and the loop will terminate.
309 Rest = Rest.substr(Idx);
310 }
311 }
312 if (EnsureNewline && !TextToWrite.ends_with(LocalEOL))
313 OS << MainEOL;
314
315 WriteFrom = WriteTo;
316}
317
318StringRef
319InclusionRewriter::getIncludedFileName(const IncludedFile *Inc) const {
320 if (Inc) {
321 auto B = SM.getBufferOrNone(Inc->Id);
322 assert(B && "Attempting to process invalid inclusion");
323 if (B)
324 return llvm::sys::path::filename(B->getBufferIdentifier());
325 }
326 return StringRef();
327}
328
329/// Print characters from \p FromFile starting at \p NextToWrite up until the
330/// inclusion directive at \p StartToken, then print out the inclusion
331/// inclusion directive disabled by a #if directive, updating \p NextToWrite
332/// and \p Line to track the number of source lines visited and the progress
333/// through the \p FromFile buffer.
334void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
335 const Token &StartToken,
336 const MemoryBufferRef &FromFile,
337 StringRef LocalEOL,
338 unsigned &NextToWrite, int &Line,
339 const IncludedFile *Inc) {
340 OutputContentUpTo(FromFile, NextToWrite,
341 SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line,
342 false);
343 Token DirectiveToken;
344 do {
345 DirectiveLex.LexFromRawLexer(DirectiveToken);
346 } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
347 if (FromFile == PredefinesBuffer) {
348 // OutputContentUpTo() would not output anything anyway.
349 return;
350 }
351 if (Inc) {
352 OS << "#if defined(__CLANG_REWRITTEN_INCLUDES) ";
353 if (isSystem(Inc->FileType))
354 OS << "|| defined(__CLANG_REWRITTEN_SYSTEM_INCLUDES) ";
355 OS << "/* " << getIncludedFileName(Inc);
356 } else {
357 OS << "#if 0 /*";
358 }
359 OS << " expanded by -frewrite-includes */" << MainEOL;
360 OutputContentUpTo(FromFile, NextToWrite,
361 SM.getFileOffset(DirectiveToken.getLocation()) +
362 DirectiveToken.getLength(),
363 LocalEOL, Line, true);
364 OS << (Inc ? "#else /* " : "#endif /*") << getIncludedFileName(Inc)
365 << " expanded by -frewrite-includes */" << MainEOL;
366}
367
368/// Find the next identifier in the pragma directive specified by \p RawToken.
369StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex,
370 Token &RawToken) {
371 RawLex.LexFromRawLexer(RawToken);
372 if (RawToken.is(tok::raw_identifier))
373 PP.LookUpIdentifierInfo(RawToken);
374 if (RawToken.is(tok::identifier))
375 return RawToken.getIdentifierInfo()->getName();
376 return StringRef();
377}
378
379/// Use a raw lexer to analyze \p FileId, incrementally copying parts of it
380/// and including content of included files recursively.
381void InclusionRewriter::Process(FileID FileId,
383 MemoryBufferRef FromFile;
384 {
385 auto B = SM.getBufferOrNone(FileId);
386 assert(B && "Attempting to process invalid inclusion");
387 if (B)
388 FromFile = *B;
389 }
390 StringRef FileName = FromFile.getBufferIdentifier();
391 Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts());
392 RawLex.SetCommentRetentionState(false);
393
394 StringRef LocalEOL = FromFile.getBuffer().detectEOL();
395
396 // Per the GNU docs: "1" indicates entering a new file.
397 if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID())
398 WriteLineInfo(FileName, 1, FileType, "");
399 else
400 WriteLineInfo(FileName, 1, FileType, " 1");
401
402 if (SM.getFileIDSize(FileId) == 0)
403 return;
404
405 // The next byte to be copied from the source file, which may be non-zero if
406 // the lexer handled a BOM.
407 unsigned NextToWrite = SM.getFileOffset(RawLex.getSourceLocation());
408 assert(SM.getLineNumber(FileId, NextToWrite) == 1);
409 int Line = 1; // The current input file line number.
410
411 Token RawToken;
412 RawLex.LexFromRawLexer(RawToken);
413
414 // TODO: Consider adding a switch that strips possibly unimportant content,
415 // such as comments, to reduce the size of repro files.
416 while (RawToken.isNot(tok::eof)) {
417 if (RawToken.is(tok::hash) && RawToken.isAtStartOfLine()) {
419 Token HashToken = RawToken;
420 RawLex.LexFromRawLexer(RawToken);
421 if (RawToken.is(tok::raw_identifier))
422 PP.LookUpIdentifierInfo(RawToken);
423 if (RawToken.getIdentifierInfo() != nullptr) {
424 switch (RawToken.getIdentifierInfo()->getPPKeywordID()) {
425 case tok::pp_include:
426 case tok::pp_include_next:
427 case tok::pp_import: {
428 SourceLocation Loc = HashToken.getLocation();
429 const IncludedFile *Inc = FindIncludeAtLocation(Loc);
430 CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
431 NextToWrite, Line, Inc);
432 if (FileId != PP.getPredefinesFileID())
433 WriteLineInfo(FileName, Line - 1, FileType, "");
434 StringRef LineInfoExtra;
435 if (const Module *Mod = FindModuleAtLocation(Loc))
436 WriteImplicitModuleImport(Mod);
437 else if (Inc) {
438 const Module *Mod = FindEnteredModule(Loc);
439 if (Mod)
440 OS << "#pragma clang module begin "
441 << Mod->getFullModuleName(true) << "\n";
442
443 // Include and recursively process the file.
444 Process(Inc->Id, Inc->FileType);
445
446 if (Mod)
447 OS << "#pragma clang module end /*"
448 << Mod->getFullModuleName(true) << "*/\n";
449 // There's no #include, therefore no #if, for -include files.
450 if (FromFile != PredefinesBuffer) {
451 OS << "#endif /* " << getIncludedFileName(Inc)
452 << " expanded by -frewrite-includes */" << LocalEOL;
453 }
454
455 // Add line marker to indicate we're returning from an included
456 // file.
457 LineInfoExtra = " 2";
458 }
459 // fix up lineinfo (since commented out directive changed line
460 // numbers) for inclusions that were skipped due to header guards
461 WriteLineInfo(FileName, Line, FileType, LineInfoExtra);
462 break;
463 }
464 case tok::pp_pragma: {
465 StringRef Identifier = NextIdentifierName(RawLex, RawToken);
466 if (Identifier == "clang" || Identifier == "GCC") {
467 if (NextIdentifierName(RawLex, RawToken) == "system_header") {
468 // keep the directive in, commented out
469 CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
470 NextToWrite, Line);
471 // update our own type
473 WriteLineInfo(FileName, Line, FileType);
474 }
475 } else if (Identifier == "once") {
476 // keep the directive in, commented out
477 CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
478 NextToWrite, Line);
479 WriteLineInfo(FileName, Line, FileType);
480 }
481 break;
482 }
483 case tok::pp_if:
484 case tok::pp_elif: {
485 bool elif = (RawToken.getIdentifierInfo()->getPPKeywordID() ==
486 tok::pp_elif);
487 bool isTrue = IsIfAtLocationTrue(RawToken.getLocation());
488 OutputContentUpTo(FromFile, NextToWrite,
489 SM.getFileOffset(HashToken.getLocation()),
490 LocalEOL, Line, /*EnsureNewline=*/true);
491 do {
492 RawLex.LexFromRawLexer(RawToken);
493 } while (!RawToken.is(tok::eod) && RawToken.isNot(tok::eof));
494 // We need to disable the old condition, but that is tricky.
495 // Trying to comment it out can easily lead to comment nesting.
496 // So instead make the condition harmless by making it enclose
497 // and empty block. Moreover, put it itself inside an #if 0 block
498 // to disable it from getting evaluated (e.g. __has_include_next
499 // warns if used from the primary source file).
500 OS << "#if 0 /* disabled by -frewrite-includes */" << MainEOL;
501 if (elif) {
502 OS << "#if 0" << MainEOL;
503 }
504 OutputContentUpTo(FromFile, NextToWrite,
505 SM.getFileOffset(RawToken.getLocation()) +
506 RawToken.getLength(),
507 LocalEOL, Line, /*EnsureNewline=*/true);
508 // Close the empty block and the disabling block.
509 OS << "#endif" << MainEOL;
510 OS << "#endif /* disabled by -frewrite-includes */" << MainEOL;
511 OS << (elif ? "#elif " : "#if ") << (isTrue ? "1" : "0")
512 << " /* evaluated by -frewrite-includes */" << MainEOL;
513 WriteLineInfo(FileName, Line, FileType);
514 break;
515 }
516 case tok::pp_endif:
517 case tok::pp_else: {
518 // We surround every #include by #if 0 to comment it out, but that
519 // changes line numbers. These are fixed up right after that, but
520 // the whole #include could be inside a preprocessor conditional
521 // that is not processed. So it is necessary to fix the line
522 // numbers one the next line after each #else/#endif as well.
523 RawLex.SetKeepWhitespaceMode(true);
524 do {
525 RawLex.LexFromRawLexer(RawToken);
526 } while (RawToken.isNot(tok::eod) && RawToken.isNot(tok::eof));
527 OutputContentUpTo(FromFile, NextToWrite,
528 SM.getFileOffset(RawToken.getLocation()) +
529 RawToken.getLength(),
530 LocalEOL, Line, /*EnsureNewline=*/ true);
531 WriteLineInfo(FileName, Line, FileType);
532 RawLex.SetKeepWhitespaceMode(false);
533 break;
534 }
535 default:
536 break;
537 }
538 }
540 }
541 RawLex.LexFromRawLexer(RawToken);
542 }
543 OutputContentUpTo(FromFile, NextToWrite,
544 SM.getFileOffset(SM.getLocForEndOfFile(FileId)), LocalEOL,
545 Line, /*EnsureNewline=*/true);
546}
547
548/// InclusionRewriterInInput - Implement -frewrite-includes mode.
550 const PreprocessorOutputOptions &Opts) {
552 InclusionRewriter *Rewrite = new InclusionRewriter(
553 PP, *OS, Opts.ShowLineMarkers, Opts.UseLineDirectives);
554 Rewrite->detectMainFileEOL();
555
556 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Rewrite));
557 PP.IgnorePragmas();
558
559 // First let the preprocessor process the entire file and call callbacks.
560 // Callbacks will record which #include's were actually performed.
562 Token Tok;
563 // Only preprocessor directives matter here, so disable macro expansion
564 // everywhere else as an optimization.
565 // TODO: It would be even faster if the preprocessor could be switched
566 // to a mode where it would parse only preprocessor directives and comments,
567 // nothing else matters for parsing or processing.
569 do {
570 PP.Lex(Tok);
571 if (Tok.is(tok::annot_module_begin))
572 Rewrite->handleModuleBegin(Tok);
573 } while (Tok.isNot(tok::eof));
574 Rewrite->setPredefinesBuffer(SM.getBufferOrFake(PP.getPredefinesFileID()));
576 Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
577 OS->flush();
578}
Token Tok
The Token.
llvm::MachO::FileType FileType
Definition MachO.h:46
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
StringRef getName() const
Return the actual identifier string.
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode.
Definition Lexer.h:254
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition Lexer.h:236
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
Definition Lexer.h:269
SourceLocation getSourceLocation(const char *Loc, unsigned TokLen=1) const
getSourceLocation - Return a source location identifier for the specified offset in the current file.
Definition Lexer.cpp:1264
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
Definition Module.cpp:240
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Definition PPCallbacks.h:37
void setParsingPreprocessorDirective(bool f)
Inform the lexer whether or not we are currently lexing a preprocessor directive.
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g....
unsigned UseLineDirectives
Use #line instead of GCC-style # N.
unsigned ShowLineMarkers
Show #line markers.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void IgnorePragmas()
Install empty handlers for all pragmas (making them ignored).
Definition Pragma.cpp:2280
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
void Lex(Token &Result)
Lex the next token for this preprocessor.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc.
SourceManager & getSourceManager() const
void SetMacroExpansionOnlyInDirectives()
Disables macro expansion everywhere except for preprocessor directives.
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
const LangOptions & getLangOpts() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
SourceLocation getLocForEndOfFile(FileID FID) const
Return the source location corresponding to the last byte of the specified file.
FileID getMainFileID() const
Returns the FileID of the main source file.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
IdentifierInfo * getIdentifierInfo() const
Definition Token.h:197
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition Token.h:142
unsigned getLength() const
Definition Token.h:145
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:104
void * getAnnotationValue() const
Definition Token.h:244
tok::TokenKind getKind() const
Definition Token.h:99
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition Token.h:286
bool isNot(tok::TokenKind K) const
Definition Token.h:111
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.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition Interp.h:987
Top level wrappers for InstallAPI frontend operations.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
Definition Template.h:54
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts)
RewriteIncludesInInput - Implement -frewrite-includes mode.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30