clang  3.8.0
InclusionRewriter.cpp
Go to the documentation of this file.
1 //===--- InclusionRewriter.cpp - Rewrite includes into their expansions ---===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This code rewrites include invocations into their expansions. This gives you
11 // a file with all included files merged into it.
12 //
13 //===----------------------------------------------------------------------===//
14 
18 #include "clang/Lex/HeaderSearch.h"
19 #include "clang/Lex/Pragma.h"
20 #include "clang/Lex/Preprocessor.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 using namespace clang;
25 using namespace llvm;
26 
27 namespace {
28 
29 class 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  const llvm::MemoryBuffer *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<unsigned, IncludedFile> FileIncludes;
47  /// Tracks where inclusions that import modules are found.
48  std::map<unsigned, const Module *> ModuleIncludes;
49  /// Used transitively for building up the FileIncludes mapping over the
50  /// various \c PPCallbacks callbacks.
51  SourceLocation LastInclusionLocation;
52 public:
53  InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers,
54  bool UseLineDirectives);
55  bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
56  void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
57  PredefinesBuffer = Buf;
58  }
59  void detectMainFileEOL();
60 private:
61  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
63  FileID PrevFID) override;
64  void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok,
65  SrcMgr::CharacteristicKind FileType) override;
66  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
67  StringRef FileName, bool IsAngled,
68  CharSourceRange FilenameRange, const FileEntry *File,
69  StringRef SearchPath, StringRef RelativePath,
70  const Module *Imported) override;
71  void WriteLineInfo(const char *Filename, int Line,
73  StringRef Extra = StringRef());
74  void WriteImplicitModuleImport(const Module *Mod);
75  void OutputContentUpTo(const MemoryBuffer &FromFile,
76  unsigned &WriteFrom, unsigned WriteTo,
77  StringRef EOL, int &lines,
78  bool EnsureNewline);
79  void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken,
80  const MemoryBuffer &FromFile, StringRef EOL,
81  unsigned &NextToWrite, int &Lines);
82  bool HandleHasInclude(FileID FileId, Lexer &RawLex,
83  const DirectoryLookup *Lookup, Token &Tok,
84  bool &FileExists);
85  const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
86  const Module *FindModuleAtLocation(SourceLocation Loc) const;
87  StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
88 };
89 
90 } // end anonymous namespace
91 
92 /// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
93 InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
94  bool ShowLineMarkers,
95  bool UseLineDirectives)
96  : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
97  PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers),
98  UseLineDirectives(UseLineDirectives),
99  LastInclusionLocation(SourceLocation()) {}
100 
101 /// Write appropriate line information as either #line directives or GNU line
102 /// markers depending on what mode we're in, including the \p Filename and
103 /// \p Line we are located at, using the specified \p EOL line separator, and
104 /// any \p Extra context specifiers in GNU line directives.
105 void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
107  StringRef Extra) {
108  if (!ShowLineMarkers)
109  return;
110  if (UseLineDirectives) {
111  OS << "#line" << ' ' << Line << ' ' << '"';
112  OS.write_escaped(Filename);
113  OS << '"';
114  } else {
115  // Use GNU linemarkers as described here:
116  // http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
117  OS << '#' << ' ' << Line << ' ' << '"';
118  OS.write_escaped(Filename);
119  OS << '"';
120  if (!Extra.empty())
121  OS << Extra;
122  if (FileType == SrcMgr::C_System)
123  // "`3' This indicates that the following text comes from a system header
124  // file, so certain warnings should be suppressed."
125  OS << " 3";
126  else if (FileType == SrcMgr::C_ExternCSystem)
127  // as above for `3', plus "`4' This indicates that the following text
128  // should be treated as being wrapped in an implicit extern "C" block."
129  OS << " 3 4";
130  }
131  OS << MainEOL;
132 }
133 
134 void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
135  OS << "@import " << Mod->getFullModuleName() << ";"
136  << " /* clang -frewrite-includes: implicit import */" << MainEOL;
137 }
138 
139 /// FileChanged - Whenever the preprocessor enters or exits a #include file
140 /// it invokes this handler.
141 void InclusionRewriter::FileChanged(SourceLocation Loc,
142  FileChangeReason Reason,
143  SrcMgr::CharacteristicKind NewFileType,
144  FileID) {
145  if (Reason != EnterFile)
146  return;
147  if (LastInclusionLocation.isInvalid())
148  // we didn't reach this file (eg: the main file) via an inclusion directive
149  return;
150  FileID Id = FullSourceLoc(Loc, SM).getFileID();
151  auto P = FileIncludes.insert(std::make_pair(
152  LastInclusionLocation.getRawEncoding(), IncludedFile(Id, NewFileType)));
153  (void)P;
154  assert(P.second && "Unexpected revisitation of the same include directive");
155  LastInclusionLocation = SourceLocation();
156 }
157 
158 /// Called whenever an inclusion is skipped due to canonical header protection
159 /// macros.
160 void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/,
161  const Token &/*FilenameTok*/,
162  SrcMgr::CharacteristicKind /*FileType*/) {
163  assert(LastInclusionLocation.isValid() &&
164  "A file, that wasn't found via an inclusion directive, was skipped");
165  LastInclusionLocation = SourceLocation();
166 }
167 
168 /// This should be called whenever the preprocessor encounters include
169 /// directives. It does not say whether the file has been included, but it
170 /// provides more information about the directive (hash location instead
171 /// of location inside the included file). It is assumed that the matching
172 /// FileChanged() or FileSkipped() is called after this.
173 void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
174  const Token &/*IncludeTok*/,
175  StringRef /*FileName*/,
176  bool /*IsAngled*/,
177  CharSourceRange /*FilenameRange*/,
178  const FileEntry * /*File*/,
179  StringRef /*SearchPath*/,
180  StringRef /*RelativePath*/,
181  const Module *Imported) {
182  assert(LastInclusionLocation.isInvalid() &&
183  "Another inclusion directive was found before the previous one "
184  "was processed");
185  if (Imported) {
186  auto P = ModuleIncludes.insert(
187  std::make_pair(HashLoc.getRawEncoding(), Imported));
188  (void)P;
189  assert(P.second && "Unexpected revisitation of the same include directive");
190  } else
191  LastInclusionLocation = HashLoc;
192 }
193 
194 /// Simple lookup for a SourceLocation (specifically one denoting the hash in
195 /// an inclusion directive) in the map of inclusion information, FileChanges.
196 const InclusionRewriter::IncludedFile *
197 InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const {
198  const auto I = FileIncludes.find(Loc.getRawEncoding());
199  if (I != FileIncludes.end())
200  return &I->second;
201  return nullptr;
202 }
203 
204 /// Simple lookup for a SourceLocation (specifically one denoting the hash in
205 /// an inclusion directive) in the map of module inclusion information.
206 const Module *
207 InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const {
208  const auto I = ModuleIncludes.find(Loc.getRawEncoding());
209  if (I != ModuleIncludes.end())
210  return I->second;
211  return nullptr;
212 }
213 
214 /// Detect the likely line ending style of \p FromFile by examining the first
215 /// newline found within it.
216 static StringRef DetectEOL(const MemoryBuffer &FromFile) {
217  // Detect what line endings the file uses, so that added content does not mix
218  // the style. We need to check for "\r\n" first because "\n\r" will match
219  // "\r\n\r\n".
220  const char *Pos = strchr(FromFile.getBufferStart(), '\n');
221  if (!Pos)
222  return "\n";
223  if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r')
224  return "\r\n";
225  if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
226  return "\n\r";
227  return "\n";
228 }
229 
230 void InclusionRewriter::detectMainFileEOL() {
231  bool Invalid;
232  const MemoryBuffer &FromFile = *SM.getBuffer(SM.getMainFileID(), &Invalid);
233  assert(!Invalid);
234  if (Invalid)
235  return; // Should never happen, but whatever.
236  MainEOL = DetectEOL(FromFile);
237 }
238 
239 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
240 /// \p WriteTo - 1.
241 void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
242  unsigned &WriteFrom, unsigned WriteTo,
243  StringRef LocalEOL, int &Line,
244  bool EnsureNewline) {
245  if (WriteTo <= WriteFrom)
246  return;
247  if (&FromFile == PredefinesBuffer) {
248  // Ignore the #defines of the predefines buffer.
249  WriteFrom = WriteTo;
250  return;
251  }
252 
253  // If we would output half of a line ending, advance one character to output
254  // the whole line ending. All buffers are null terminated, so looking ahead
255  // one byte is safe.
256  if (LocalEOL.size() == 2 &&
257  LocalEOL[0] == (FromFile.getBufferStart() + WriteTo)[-1] &&
258  LocalEOL[1] == (FromFile.getBufferStart() + WriteTo)[0])
259  WriteTo++;
260 
261  StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom,
262  WriteTo - WriteFrom);
263 
264  if (MainEOL == LocalEOL) {
265  OS << TextToWrite;
266  // count lines manually, it's faster than getPresumedLoc()
267  Line += TextToWrite.count(LocalEOL);
268  if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
269  OS << MainEOL;
270  } else {
271  // Output the file one line at a time, rewriting the line endings as we go.
272  StringRef Rest = TextToWrite;
273  while (!Rest.empty()) {
274  StringRef LineText;
275  std::tie(LineText, Rest) = Rest.split(LocalEOL);
276  OS << LineText;
277  Line++;
278  if (!Rest.empty())
279  OS << MainEOL;
280  }
281  if (TextToWrite.endswith(LocalEOL) || EnsureNewline)
282  OS << MainEOL;
283  }
284  WriteFrom = WriteTo;
285 }
286 
287 /// Print characters from \p FromFile starting at \p NextToWrite up until the
288 /// inclusion directive at \p StartToken, then print out the inclusion
289 /// inclusion directive disabled by a #if directive, updating \p NextToWrite
290 /// and \p Line to track the number of source lines visited and the progress
291 /// through the \p FromFile buffer.
292 void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
293  const Token &StartToken,
294  const MemoryBuffer &FromFile,
295  StringRef LocalEOL,
296  unsigned &NextToWrite, int &Line) {
297  OutputContentUpTo(FromFile, NextToWrite,
298  SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line,
299  false);
300  Token DirectiveToken;
301  do {
302  DirectiveLex.LexFromRawLexer(DirectiveToken);
303  } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
304  if (&FromFile == PredefinesBuffer) {
305  // OutputContentUpTo() would not output anything anyway.
306  return;
307  }
308  OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL;
309  OutputContentUpTo(FromFile, NextToWrite,
310  SM.getFileOffset(DirectiveToken.getLocation()) +
311  DirectiveToken.getLength(),
312  LocalEOL, Line, true);
313  OS << "#endif /* expanded by -frewrite-includes */" << MainEOL;
314 }
315 
316 /// Find the next identifier in the pragma directive specified by \p RawToken.
317 StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex,
318  Token &RawToken) {
319  RawLex.LexFromRawLexer(RawToken);
320  if (RawToken.is(tok::raw_identifier))
321  PP.LookUpIdentifierInfo(RawToken);
322  if (RawToken.is(tok::identifier))
323  return RawToken.getIdentifierInfo()->getName();
324  return StringRef();
325 }
326 
327 // Expand __has_include and __has_include_next if possible. If there's no
328 // definitive answer return false.
329 bool InclusionRewriter::HandleHasInclude(
330  FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
331  bool &FileExists) {
332  // Lex the opening paren.
333  RawLex.LexFromRawLexer(Tok);
334  if (Tok.isNot(tok::l_paren))
335  return false;
336 
337  RawLex.LexFromRawLexer(Tok);
338 
339  SmallString<128> FilenameBuffer;
340  StringRef Filename;
341  // Since the raw lexer doesn't give us angle_literals we have to parse them
342  // ourselves.
343  // FIXME: What to do if the file name is a macro?
344  if (Tok.is(tok::less)) {
345  RawLex.LexFromRawLexer(Tok);
346 
347  FilenameBuffer += '<';
348  do {
349  if (Tok.is(tok::eod)) // Sanity check.
350  return false;
351 
352  if (Tok.is(tok::raw_identifier))
353  PP.LookUpIdentifierInfo(Tok);
354 
355  // Get the string piece.
356  SmallVector<char, 128> TmpBuffer;
357  bool Invalid = false;
358  StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid);
359  if (Invalid)
360  return false;
361 
362  FilenameBuffer += TmpName;
363 
364  RawLex.LexFromRawLexer(Tok);
365  } while (Tok.isNot(tok::greater));
366 
367  FilenameBuffer += '>';
368  Filename = FilenameBuffer;
369  } else {
370  if (Tok.isNot(tok::string_literal))
371  return false;
372 
373  bool Invalid = false;
374  Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
375  if (Invalid)
376  return false;
377  }
378 
379  // Lex the closing paren.
380  RawLex.LexFromRawLexer(Tok);
381  if (Tok.isNot(tok::r_paren))
382  return false;
383 
384  // Now ask HeaderInfo if it knows about the header.
385  // FIXME: Subframeworks aren't handled here. Do we care?
386  bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
387  const DirectoryLookup *CurDir;
388  const FileEntry *FileEnt = PP.getSourceManager().getFileEntryForID(FileId);
390  Includers;
391  Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
392  // FIXME: Why don't we call PP.LookupFile here?
393  const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
394  Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
395  nullptr, nullptr, nullptr, false);
396 
397  FileExists = File != nullptr;
398  return true;
399 }
400 
401 /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it
402 /// and including content of included files recursively.
403 bool InclusionRewriter::Process(FileID FileId,
405 {
406  bool Invalid;
407  const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
408  assert(!Invalid && "Attempting to process invalid inclusion");
409  const char *FileName = FromFile.getBufferIdentifier();
410  Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
411  RawLex.SetCommentRetentionState(false);
412 
413  StringRef LocalEOL = DetectEOL(FromFile);
414 
415  // Per the GNU docs: "1" indicates entering a new file.
416  if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID())
417  WriteLineInfo(FileName, 1, FileType, "");
418  else
419  WriteLineInfo(FileName, 1, FileType, " 1");
420 
421  if (SM.getFileIDSize(FileId) == 0)
422  return false;
423 
424  // The next byte to be copied from the source file, which may be non-zero if
425  // the lexer handled a BOM.
426  unsigned NextToWrite = SM.getFileOffset(RawLex.getSourceLocation());
427  assert(SM.getLineNumber(FileId, NextToWrite) == 1);
428  int Line = 1; // The current input file line number.
429 
430  Token RawToken;
431  RawLex.LexFromRawLexer(RawToken);
432 
433  // TODO: Consider adding a switch that strips possibly unimportant content,
434  // such as comments, to reduce the size of repro files.
435  while (RawToken.isNot(tok::eof)) {
436  if (RawToken.is(tok::hash) && RawToken.isAtStartOfLine()) {
437  RawLex.setParsingPreprocessorDirective(true);
438  Token HashToken = RawToken;
439  RawLex.LexFromRawLexer(RawToken);
440  if (RawToken.is(tok::raw_identifier))
441  PP.LookUpIdentifierInfo(RawToken);
442  if (RawToken.getIdentifierInfo() != nullptr) {
443  switch (RawToken.getIdentifierInfo()->getPPKeywordID()) {
444  case tok::pp_include:
445  case tok::pp_include_next:
446  case tok::pp_import: {
447  CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL, NextToWrite,
448  Line);
449  if (FileId != PP.getPredefinesFileID())
450  WriteLineInfo(FileName, Line - 1, FileType, "");
451  StringRef LineInfoExtra;
452  SourceLocation Loc = HashToken.getLocation();
453  if (const Module *Mod = FindModuleAtLocation(Loc))
454  WriteImplicitModuleImport(Mod);
455  else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
456  // include and recursively process the file
457  if (Process(Inc->Id, Inc->FileType)) {
458  // and set lineinfo back to this file, if the nested one was
459  // actually included
460  // `2' indicates returning to a file (after having included
461  // another file.
462  LineInfoExtra = " 2";
463  }
464  }
465  // fix up lineinfo (since commented out directive changed line
466  // numbers) for inclusions that were skipped due to header guards
467  WriteLineInfo(FileName, Line, FileType, LineInfoExtra);
468  break;
469  }
470  case tok::pp_pragma: {
471  StringRef Identifier = NextIdentifierName(RawLex, RawToken);
472  if (Identifier == "clang" || Identifier == "GCC") {
473  if (NextIdentifierName(RawLex, RawToken) == "system_header") {
474  // keep the directive in, commented out
475  CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
476  NextToWrite, Line);
477  // update our own type
478  FileType = SM.getFileCharacteristic(RawToken.getLocation());
479  WriteLineInfo(FileName, Line, FileType);
480  }
481  } else if (Identifier == "once") {
482  // keep the directive in, commented out
483  CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
484  NextToWrite, Line);
485  WriteLineInfo(FileName, Line, FileType);
486  }
487  break;
488  }
489  case tok::pp_if:
490  case tok::pp_elif: {
491  bool elif = (RawToken.getIdentifierInfo()->getPPKeywordID() ==
492  tok::pp_elif);
493  // Rewrite special builtin macros to avoid pulling in host details.
494  do {
495  // Walk over the directive.
496  RawLex.LexFromRawLexer(RawToken);
497  if (RawToken.is(tok::raw_identifier))
498  PP.LookUpIdentifierInfo(RawToken);
499 
500  if (RawToken.is(tok::identifier)) {
501  bool HasFile;
502  SourceLocation Loc = RawToken.getLocation();
503 
504  // Rewrite __has_include(x)
505  if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
506  if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
507  HasFile))
508  continue;
509  // Rewrite __has_include_next(x)
510  } else if (RawToken.getIdentifierInfo()->isStr(
511  "__has_include_next")) {
512  const DirectoryLookup *Lookup = PP.GetCurDirLookup();
513  if (Lookup)
514  ++Lookup;
515 
516  if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken,
517  HasFile))
518  continue;
519  } else {
520  continue;
521  }
522  // Replace the macro with (0) or (1), followed by the commented
523  // out macro for reference.
524  OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
525  LocalEOL, Line, false);
526  OS << '(' << (int) HasFile << ")/*";
527  OutputContentUpTo(FromFile, NextToWrite,
528  SM.getFileOffset(RawToken.getLocation()) +
529  RawToken.getLength(),
530  LocalEOL, Line, false);
531  OS << "*/";
532  }
533  } while (RawToken.isNot(tok::eod));
534  if (elif) {
535  OutputContentUpTo(FromFile, NextToWrite,
536  SM.getFileOffset(RawToken.getLocation()) +
537  RawToken.getLength(),
538  LocalEOL, Line, /*EnsureNewline=*/ true);
539  WriteLineInfo(FileName, Line, FileType);
540  }
541  break;
542  }
543  case tok::pp_endif:
544  case tok::pp_else: {
545  // We surround every #include by #if 0 to comment it out, but that
546  // changes line numbers. These are fixed up right after that, but
547  // the whole #include could be inside a preprocessor conditional
548  // that is not processed. So it is necessary to fix the line
549  // numbers one the next line after each #else/#endif as well.
550  RawLex.SetKeepWhitespaceMode(true);
551  do {
552  RawLex.LexFromRawLexer(RawToken);
553  } while (RawToken.isNot(tok::eod) && RawToken.isNot(tok::eof));
554  OutputContentUpTo(FromFile, NextToWrite,
555  SM.getFileOffset(RawToken.getLocation()) +
556  RawToken.getLength(),
557  LocalEOL, Line, /*EnsureNewline=*/ true);
558  WriteLineInfo(FileName, Line, FileType);
559  RawLex.SetKeepWhitespaceMode(false);
560  }
561  default:
562  break;
563  }
564  }
565  RawLex.setParsingPreprocessorDirective(false);
566  }
567  RawLex.LexFromRawLexer(RawToken);
568  }
569  OutputContentUpTo(FromFile, NextToWrite,
570  SM.getFileOffset(SM.getLocForEndOfFile(FileId)), LocalEOL,
571  Line, /*EnsureNewline=*/true);
572  return true;
573 }
574 
575 /// InclusionRewriterInInput - Implement -frewrite-includes mode.
576 void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
577  const PreprocessorOutputOptions &Opts) {
579  InclusionRewriter *Rewrite = new InclusionRewriter(
580  PP, *OS, Opts.ShowLineMarkers, Opts.UseLineDirectives);
581  Rewrite->detectMainFileEOL();
582 
583  PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Rewrite));
584  PP.IgnorePragmas();
585 
586  // First let the preprocessor process the entire file and call callbacks.
587  // Callbacks will record which #include's were actually performed.
588  PP.EnterMainSourceFile();
589  Token Tok;
590  // Only preprocessor directives matter here, so disable macro expansion
591  // everywhere else as an optimization.
592  // TODO: It would be even faster if the preprocessor could be switched
593  // to a mode where it would parse only preprocessor directives and comments,
594  // nothing else matters for parsing or processing.
596  do {
597  PP.Lex(Tok);
598  } while (Tok.isNot(tok::eof));
599  Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID()));
600  Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User);
601  Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
602  OS->flush();
603 }
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition: Token.h:261
SourceManager & getSourceManager() const
Definition: Preprocessor.h:687
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
Definition: Lexer.h:46
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition: Lexer.h:154
Defines the SourceManager interface.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
FileID getFileID() const
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
void IgnorePragmas()
Install empty handlers for all pragmas (making them ignored).
Definition: Pragma.cpp:1488
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:79
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:38
std::string getFullModuleName() const
Retrieve the full name of this module, including the path from its top-level module.
Token - This structure provides full information about a lexed token.
Definition: Token.h:37
Describes a module or submodule.
Definition: Basic/Module.h:47
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
void setParsingPreprocessorDirective(bool f)
Inform the lexer whether or not we are currently lexing a preprocessor directive. ...
detail::InMemoryDirectory::const_iterator I
static StringRef DetectEOL(const MemoryBuffer &FromFile)
Detect the likely line ending style of FromFile by examining the first newline found within it...
AnnotatingParser & P
SourceLocation getLocForEndOfFile(FileID FID) const
Return the source location corresponding to the last byte of the specified file.
StringRef Filename
Definition: Format.cpp:1723
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g., -E).
SourceManager & SM
StringRef getName() const
Return the actual identifier string.
Represents a character-granular source range.
void SetMacroExpansionOnlyInDirectives()
Disables macro expansion everywhere except for preprocessor directives.
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc...
Defines the clang::Preprocessor interface.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
bool isNot(tok::TokenKind K) const
Definition: Token.h:96
Record the location of an inclusion directive, such as an #include or #import statement.
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
Encodes a location in the source.
AnnotatedLine & Line
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:53
void Lex(Token &Result)
Lex the next token for this preprocessor.
unsigned UseLineDirectives
Use #line instead of GCC-style # N.
FileID getMainFileID() const
Returns the FileID of the main source file.
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:95
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
Definition: Preprocessor.h:770
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts)
RewriteIncludesInInput - Implement -frewrite-includes mode.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
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:1043
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
unsigned ShowLineMarkers
Show #line markers.
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode...
Definition: Lexer.h:187
A SourceLocation and its associated SourceManager.
unsigned getLength() const
Definition: Token.h:127
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
const DirectoryEntry * getDir() const
Return the directory the file lives in.
Definition: FileManager.h:93
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode...
Definition: Lexer.h:172
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:778
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:96
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.