clang  3.9.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 = PP.getLangOpts().ObjC2
454  ? FindModuleAtLocation(Loc)
455  : nullptr)
456  WriteImplicitModuleImport(Mod);
457  else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
458  // include and recursively process the file
459  if (Process(Inc->Id, Inc->FileType)) {
460  // and set lineinfo back to this file, if the nested one was
461  // actually included
462  // `2' indicates returning to a file (after having included
463  // another file.
464  LineInfoExtra = " 2";
465  }
466  }
467  // fix up lineinfo (since commented out directive changed line
468  // numbers) for inclusions that were skipped due to header guards
469  WriteLineInfo(FileName, Line, FileType, LineInfoExtra);
470  break;
471  }
472  case tok::pp_pragma: {
473  StringRef Identifier = NextIdentifierName(RawLex, RawToken);
474  if (Identifier == "clang" || Identifier == "GCC") {
475  if (NextIdentifierName(RawLex, RawToken) == "system_header") {
476  // keep the directive in, commented out
477  CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
478  NextToWrite, Line);
479  // update our own type
480  FileType = SM.getFileCharacteristic(RawToken.getLocation());
481  WriteLineInfo(FileName, Line, FileType);
482  }
483  } else if (Identifier == "once") {
484  // keep the directive in, commented out
485  CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
486  NextToWrite, Line);
487  WriteLineInfo(FileName, Line, FileType);
488  }
489  break;
490  }
491  case tok::pp_if:
492  case tok::pp_elif: {
493  bool elif = (RawToken.getIdentifierInfo()->getPPKeywordID() ==
494  tok::pp_elif);
495  // Rewrite special builtin macros to avoid pulling in host details.
496  do {
497  // Walk over the directive.
498  RawLex.LexFromRawLexer(RawToken);
499  if (RawToken.is(tok::raw_identifier))
500  PP.LookUpIdentifierInfo(RawToken);
501 
502  if (RawToken.is(tok::identifier)) {
503  bool HasFile;
504  SourceLocation Loc = RawToken.getLocation();
505 
506  // Rewrite __has_include(x)
507  if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
508  if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
509  HasFile))
510  continue;
511  // Rewrite __has_include_next(x)
512  } else if (RawToken.getIdentifierInfo()->isStr(
513  "__has_include_next")) {
514  const DirectoryLookup *Lookup = PP.GetCurDirLookup();
515  if (Lookup)
516  ++Lookup;
517 
518  if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken,
519  HasFile))
520  continue;
521  } else {
522  continue;
523  }
524  // Replace the macro with (0) or (1), followed by the commented
525  // out macro for reference.
526  OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
527  LocalEOL, Line, false);
528  OS << '(' << (int) HasFile << ")/*";
529  OutputContentUpTo(FromFile, NextToWrite,
530  SM.getFileOffset(RawToken.getLocation()) +
531  RawToken.getLength(),
532  LocalEOL, Line, false);
533  OS << "*/";
534  }
535  } while (RawToken.isNot(tok::eod));
536  if (elif) {
537  OutputContentUpTo(FromFile, NextToWrite,
538  SM.getFileOffset(RawToken.getLocation()) +
539  RawToken.getLength(),
540  LocalEOL, Line, /*EnsureNewline=*/ true);
541  WriteLineInfo(FileName, Line, FileType);
542  }
543  break;
544  }
545  case tok::pp_endif:
546  case tok::pp_else: {
547  // We surround every #include by #if 0 to comment it out, but that
548  // changes line numbers. These are fixed up right after that, but
549  // the whole #include could be inside a preprocessor conditional
550  // that is not processed. So it is necessary to fix the line
551  // numbers one the next line after each #else/#endif as well.
552  RawLex.SetKeepWhitespaceMode(true);
553  do {
554  RawLex.LexFromRawLexer(RawToken);
555  } while (RawToken.isNot(tok::eod) && RawToken.isNot(tok::eof));
556  OutputContentUpTo(FromFile, NextToWrite,
557  SM.getFileOffset(RawToken.getLocation()) +
558  RawToken.getLength(),
559  LocalEOL, Line, /*EnsureNewline=*/ true);
560  WriteLineInfo(FileName, Line, FileType);
561  RawLex.SetKeepWhitespaceMode(false);
562  }
563  default:
564  break;
565  }
566  }
567  RawLex.setParsingPreprocessorDirective(false);
568  }
569  RawLex.LexFromRawLexer(RawToken);
570  }
571  OutputContentUpTo(FromFile, NextToWrite,
572  SM.getFileOffset(SM.getLocForEndOfFile(FileId)), LocalEOL,
573  Line, /*EnsureNewline=*/true);
574  return true;
575 }
576 
577 /// InclusionRewriterInInput - Implement -frewrite-includes mode.
578 void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
579  const PreprocessorOutputOptions &Opts) {
581  InclusionRewriter *Rewrite = new InclusionRewriter(
582  PP, *OS, Opts.ShowLineMarkers, Opts.UseLineDirectives);
583  Rewrite->detectMainFileEOL();
584 
585  PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Rewrite));
586  PP.IgnorePragmas();
587 
588  // First let the preprocessor process the entire file and call callbacks.
589  // Callbacks will record which #include's were actually performed.
590  PP.EnterMainSourceFile();
591  Token Tok;
592  // Only preprocessor directives matter here, so disable macro expansion
593  // everywhere else as an optimization.
594  // TODO: It would be even faster if the preprocessor could be switched
595  // to a mode where it would parse only preprocessor directives and comments,
596  // nothing else matters for parsing or processing.
598  do {
599  PP.Lex(Tok);
600  } while (Tok.isNot(tok::eof));
601  Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID()));
602  Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User);
603  Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
604  OS->flush();
605 }
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition: Token.h:265
SourceManager & getSourceManager() const
Definition: Preprocessor.h:694
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.
StringRef P
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:1506
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:78
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:35
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...
SourceLocation getLocForEndOfFile(FileID FID) const
Return the source location corresponding to the last byte of the specified file.
StringRef Filename
Definition: Format.cpp:1194
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g., -E).
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:123
bool isNot(tok::TokenKind K) const
Definition: Token.h:95
Record the location of an inclusion directive, such as an #include or #import statement.
const SourceManager & SM
Definition: Format.cpp:1184
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
StringRef FileName
Definition: Format.cpp:1313
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:94
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
Definition: Preprocessor.h:777
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:1070
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:126
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:95
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:785
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:97
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:176
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.