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