18c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===--- InclusionRewriter.cpp - Rewrite includes into their expansions ---===//
28c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//
38c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//                     The LLVM Compiler Infrastructure
48c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//
58c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// This file is distributed under the University of Illinois Open Source
68c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// License. See LICENSE.TXT for details.
78c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//
88c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===//
98c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//
108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// This code rewrites include invocations into their expansions.  This gives you
118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// a file with all included files merged into it.
128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//
138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===//
148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
15305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Frontend/Rewriters.h"
168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie#include "clang/Basic/SourceManager.h"
178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie#include "clang/Frontend/PreprocessorOutputOptions.h"
18596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer#include "clang/Lex/HeaderSearch.h"
198ee6a0dcc985c65bf5fd61a63e3f86e3ac516f5eLubos Lunak#include "clang/Lex/Pragma.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h"
21596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer#include "llvm/ADT/SmallString.h"
228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie#include "llvm/Support/raw_ostream.h"
238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing namespace clang;
258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing namespace llvm;
268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikienamespace {
288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieclass InclusionRewriter : public PPCallbacks {
308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// Information about which #includes were actually performed,
318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// created by preprocessor callbacks.
328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  struct FileChange {
3303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    const Module *Mod;
348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SourceLocation From;
358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    FileID Id;
368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SrcMgr::CharacteristicKind FileType;
3703409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    FileChange(SourceLocation From, const Module *Mod) : Mod(Mod), From(From) {
388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    }
398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  };
4049fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  Preprocessor &PP; ///< Used to find inclusion directives.
4149fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  SourceManager &SM; ///< Used to read and manage source files.
4249fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  raw_ostream &OS; ///< The destination stream for rewritten contents.
43e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines.
4449fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  bool ShowLineMarkers; ///< Show #line markers.
4549fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  bool UseLineDirective; ///< Use of line directives or line markers.
468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  typedef std::map<unsigned, FileChange> FileChangeMap;
47959dc8475fc20ce8c3fd55021cb9f02a531cddc5Dmitri Gribenko  FileChangeMap FileChanges; ///< Tracks which files were included where.
488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// Used transitively for building up the FileChanges mapping over the
498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// various \c PPCallbacks callbacks.
508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChangeMap::iterator LastInsertedFileChange;
518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiepublic:
528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers);
538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
54e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
55e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis    PredefinesBuffer = Buf;
56e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  }
578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieprivate:
58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   SrcMgr::CharacteristicKind FileType,
60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   FileID PrevFID) override;
61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void FileSkipped(const FileEntry &ParentFile, const Token &FilenameTok,
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   SrcMgr::CharacteristicKind FileType) override;
63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef FileName, bool IsAngled,
65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          CharSourceRange FilenameRange, const FileEntry *File,
66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef SearchPath, StringRef RelativePath,
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          const Module *Imported) override;
688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  void WriteLineInfo(const char *Filename, int Line,
698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                     SrcMgr::CharacteristicKind FileType,
708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                     StringRef EOL, StringRef Extra = StringRef());
7103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis  void WriteImplicitModuleImport(const Module *Mod, StringRef EOL);
728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  void OutputContentUpTo(const MemoryBuffer &FromFile,
738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                         unsigned &WriteFrom, unsigned WriteTo,
748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                         StringRef EOL, int &lines,
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         bool EnsureNewline);
768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken,
778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           const MemoryBuffer &FromFile, StringRef EOL,
788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           unsigned &NextToWrite, int &Lines);
79596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  bool HandleHasInclude(FileID FileId, Lexer &RawLex,
80596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                        const DirectoryLookup *Lookup, Token &Tok,
81596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                        bool &FileExists);
828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const FileChange *FindFileChangeLocation(SourceLocation Loc) const;
838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie};
858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}  // end anonymous namespace
878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieInclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                     bool ShowLineMarkers)
916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  : PP(PP), SM(PP.getSourceManager()), OS(OS), PredefinesBuffer(nullptr),
928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    ShowLineMarkers(ShowLineMarkers),
938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    LastInsertedFileChange(FileChanges.end()) {
948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // If we're in microsoft mode, use normal #line instead of line markers.
958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  UseLineDirective = PP.getLangOpts().MicrosoftExt;
968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Write appropriate line information as either #line directives or GNU line
998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// markers depending on what mode we're in, including the \p Filename and
1008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// \p Line we are located at, using the specified \p EOL line separator, and
1018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// any \p Extra context specifiers in GNU line directives.
1028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
1038c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                      SrcMgr::CharacteristicKind FileType,
1048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                      StringRef EOL, StringRef Extra) {
1058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (!ShowLineMarkers)
1068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (UseLineDirective) {
108a2b4754bb241bb21b94832916ee07cbf7351b958Eli Friedman    OS << "#line" << ' ' << Line << ' ' << '"';
109a2b4754bb241bb21b94832916ee07cbf7351b958Eli Friedman    OS.write_escaped(Filename);
110a2b4754bb241bb21b94832916ee07cbf7351b958Eli Friedman    OS << '"';
1118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } else {
1128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // Use GNU linemarkers as described here:
1138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
1143432b7800d447267f4353e70a319f6f5a0bb4aabEli Friedman    OS << '#' << ' ' << Line << ' ' << '"';
1153432b7800d447267f4353e70a319f6f5a0bb4aabEli Friedman    OS.write_escaped(Filename);
1163432b7800d447267f4353e70a319f6f5a0bb4aabEli Friedman    OS << '"';
1178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (!Extra.empty())
1188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << Extra;
1198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (FileType == SrcMgr::C_System)
1208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // "`3' This indicates that the following text comes from a system header
1218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // file, so certain warnings should be suppressed."
1228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << " 3";
1238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    else if (FileType == SrcMgr::C_ExternCSystem)
1248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // as above for `3', plus "`4' This indicates that the following text
1258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // should be treated as being wrapped in an implicit extern "C" block."
1268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << " 3 4";
1278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
1288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS << EOL;
1298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
13103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidisvoid InclusionRewriter::WriteImplicitModuleImport(const Module *Mod,
13203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                                                  StringRef EOL) {
13303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis  OS << "@import " << Mod->getFullModuleName() << ";"
13403409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis     << " /* clang -frewrite-includes: implicit import */" << EOL;
13503409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis}
13603409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis
1378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// FileChanged - Whenever the preprocessor enters or exits a #include file
1388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// it invokes this handler.
1398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::FileChanged(SourceLocation Loc,
1408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    FileChangeReason Reason,
1418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    SrcMgr::CharacteristicKind NewFileType,
1428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    FileID) {
1438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Reason != EnterFile)
1448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (LastInsertedFileChange == FileChanges.end())
1468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // we didn't reach this file (eg: the main file) via an inclusion directive
1478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange->second.Id = FullSourceLoc(Loc, SM).getFileID();
1498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange->second.FileType = NewFileType;
1508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange = FileChanges.end();
1518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Called whenever an inclusion is skipped due to canonical header protection
1548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// macros.
1558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::FileSkipped(const FileEntry &/*ParentFile*/,
1568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    const Token &/*FilenameTok*/,
1578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    SrcMgr::CharacteristicKind /*FileType*/) {
1588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(LastInsertedFileChange != FileChanges.end() && "A file, that wasn't "
1598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    "found via an inclusion directive, was skipped");
1608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChanges.erase(LastInsertedFileChange);
1618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange = FileChanges.end();
1628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// This should be called whenever the preprocessor encounters include
1658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// directives. It does not say whether the file has been included, but it
1668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// provides more information about the directive (hash location instead
1678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// of location inside the included file). It is assumed that the matching
1688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// FileChanged() or FileSkipped() is called after this.
1698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
1708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           const Token &/*IncludeTok*/,
1718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           StringRef /*FileName*/,
1728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           bool /*IsAngled*/,
173da313592441db36cf4b06be97c4bcc238ee6fa9cArgyrios Kyrtzidis                                           CharSourceRange /*FilenameRange*/,
1748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           const FileEntry * /*File*/,
1758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           StringRef /*SearchPath*/,
176f8afcffe6a0213760b64c211812b1750e1e1e967Argyrios Kyrtzidis                                           StringRef /*RelativePath*/,
17703409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                                           const Module *Imported) {
1788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
1798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    "directive was found before the previous one was processed");
1808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
18103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc, Imported)));
1828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(p.second && "Unexpected revisitation of the same include directive");
18303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis  if (!Imported)
18403409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    LastInsertedFileChange = p.first;
1858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Simple lookup for a SourceLocation (specifically one denoting the hash in
1888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// an inclusion directive) in the map of inclusion information, FileChanges.
1898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieconst InclusionRewriter::FileChange *
1908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieInclusionRewriter::FindFileChangeLocation(SourceLocation Loc) const {
1918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChangeMap::const_iterator I = FileChanges.find(Loc.getRawEncoding());
1928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (I != FileChanges.end())
1938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return &I->second;
1946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
1958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Detect the likely line ending style of \p FromFile by examining the first
1988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// newline found within it.
1998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiestatic StringRef DetectEOL(const MemoryBuffer &FromFile) {
2008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // detect what line endings the file uses, so that added content does not mix
2018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // the style
2028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const char *Pos = strchr(FromFile.getBufferStart(), '\n');
2036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!Pos)
2048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\n";
2058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
2068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\n\r";
2078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r')
2088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\r\n";
2098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return "\n";
2108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
2138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// \p WriteTo - 1.
2148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
2158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          unsigned &WriteFrom, unsigned WriteTo,
2168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          StringRef EOL, int &Line,
2178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          bool EnsureNewline) {
2188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (WriteTo <= WriteFrom)
2198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
220e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  if (&FromFile == PredefinesBuffer) {
221e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis    // Ignore the #defines of the predefines buffer.
222e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis    WriteFrom = WriteTo;
223e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis    return;
224e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  }
2258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS.write(FromFile.getBufferStart() + WriteFrom, WriteTo - WriteFrom);
2268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // count lines manually, it's faster than getPresumedLoc()
2273159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer  Line += std::count(FromFile.getBufferStart() + WriteFrom,
2283159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer                     FromFile.getBufferStart() + WriteTo, '\n');
2298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (EnsureNewline) {
2308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    char LastChar = FromFile.getBufferStart()[WriteTo - 1];
2318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (LastChar != '\n' && LastChar != '\r')
2328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << EOL;
2338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
2348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  WriteFrom = WriteTo;
2358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Print characters from \p FromFile starting at \p NextToWrite up until the
2388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// inclusion directive at \p StartToken, then print out the inclusion
2398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// inclusion directive disabled by a #if directive, updating \p NextToWrite
2408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// and \p Line to track the number of source lines visited and the progress
2418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// through the \p FromFile buffer.
2428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
2438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            const Token &StartToken,
2448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            const MemoryBuffer &FromFile,
2458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            StringRef EOL,
2468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            unsigned &NextToWrite, int &Line) {
2478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    SM.getFileOffset(StartToken.getLocation()), EOL, Line, false);
2498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token DirectiveToken;
2508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  do {
2518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    DirectiveLex.LexFromRawLexer(DirectiveToken);
2528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
2536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (&FromFile == PredefinesBuffer) {
2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // OutputContentUpTo() would not output anything anyway.
2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return;
2566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
25760ad16b7e24cdb88c577c107b69da85458000858David Blaikie  OS << "#if 0 /* expanded by -frewrite-includes */" << EOL;
2588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
2598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SM.getFileOffset(DirectiveToken.getLocation()) + DirectiveToken.getLength(),
260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    EOL, Line, true);
26160ad16b7e24cdb88c577c107b69da85458000858David Blaikie  OS << "#endif /* expanded by -frewrite-includes */" << EOL;
2628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Find the next identifier in the pragma directive specified by \p RawToken.
2658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieStringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex,
2668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                                Token &RawToken) {
2678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.LexFromRawLexer(RawToken);
2688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (RawToken.is(tok::raw_identifier))
2698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    PP.LookUpIdentifierInfo(RawToken);
2708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (RawToken.is(tok::identifier))
2718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return RawToken.getIdentifierInfo()->getName();
2728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return StringRef();
2738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
275596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer// Expand __has_include and __has_include_next if possible. If there's no
276596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer// definitive answer return false.
277596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramerbool InclusionRewriter::HandleHasInclude(
278596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
279596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    bool &FileExists) {
280596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Lex the opening paren.
281596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
282596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.isNot(tok::l_paren))
283596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    return false;
284596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
285596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
286596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
287596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  SmallString<128> FilenameBuffer;
288596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  StringRef Filename;
289596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Since the raw lexer doesn't give us angle_literals we have to parse them
290596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // ourselves.
291596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // FIXME: What to do if the file name is a macro?
292596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.is(tok::less)) {
293596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    RawLex.LexFromRawLexer(Tok);
294596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
295596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FilenameBuffer += '<';
296596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    do {
297596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Tok.is(tok::eod)) // Sanity check.
298596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        return false;
299596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
300596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Tok.is(tok::raw_identifier))
301596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        PP.LookUpIdentifierInfo(Tok);
302596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
303596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      // Get the string piece.
304596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      SmallVector<char, 128> TmpBuffer;
305596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      bool Invalid = false;
306596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid);
307596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Invalid)
308596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        return false;
309596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
310596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      FilenameBuffer += TmpName;
311596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
312596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      RawLex.LexFromRawLexer(Tok);
313596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    } while (Tok.isNot(tok::greater));
314596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
315596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FilenameBuffer += '>';
316596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    Filename = FilenameBuffer;
317596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  } else {
318596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    if (Tok.isNot(tok::string_literal))
319596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      return false;
320596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
321596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    bool Invalid = false;
322596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
323596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    if (Invalid)
324596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      return false;
325596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  }
326596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
327596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Lex the closing paren.
328596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
329596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.isNot(tok::r_paren))
330596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    return false;
331596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
332596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Now ask HeaderInfo if it knows about the header.
333596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // FIXME: Subframeworks aren't handled here. Do we care?
334596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
335596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  const DirectoryLookup *CurDir;
336596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
3376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Filename, SourceLocation(), isAngled, nullptr, CurDir,
3386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      PP.getSourceManager().getFileEntryForID(FileId), nullptr, nullptr,
3396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      nullptr, false);
340596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
3416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FileExists = File != nullptr;
342596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  return true;
343596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer}
344596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
3451505edfeb85f54f2a982f76542b51e5ddd12b44cBenjamin Kramer/// Use a raw lexer to analyze \p FileId, incrementally copying parts of it
3468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// and including content of included files recursively.
3478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiebool InclusionRewriter::Process(FileID FileId,
3488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                SrcMgr::CharacteristicKind FileType)
3498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie{
3508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  bool Invalid;
3518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
352bae2b31822e3c2139b5f8fbb127e4c5674cce6dbDavid Blaikie  if (Invalid) // invalid inclusion
353507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis    return false;
3548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const char *FileName = FromFile.getBufferIdentifier();
3558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
3568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.SetCommentRetentionState(false);
3578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  StringRef EOL = DetectEOL(FromFile);
3598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Per the GNU docs: "1" indicates entering a new file.
3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID())
3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    WriteLineInfo(FileName, 1, FileType, EOL, "");
3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  else
3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    WriteLineInfo(FileName, 1, FileType, EOL, " 1");
3658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (SM.getFileIDSize(FileId) == 0)
367507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis    return false;
3688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // The next byte to be copied from the source file, which may be non-zero if
370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // the lexer handled a BOM.
371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned NextToWrite = SM.getFileOffset(RawLex.getSourceLocation());
372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(SM.getLineNumber(FileId, NextToWrite) == 1);
3738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  int Line = 1; // The current input file line number.
3748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token RawToken;
3768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.LexFromRawLexer(RawToken);
3778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // TODO: Consider adding a switch that strips possibly unimportant content,
3798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // such as comments, to reduce the size of repro files.
3808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  while (RawToken.isNot(tok::eof)) {
3818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (RawToken.is(tok::hash) && RawToken.isAtStartOfLine()) {
3828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.setParsingPreprocessorDirective(true);
3838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      Token HashToken = RawToken;
3848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.LexFromRawLexer(RawToken);
3858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      if (RawToken.is(tok::raw_identifier))
3868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        PP.LookUpIdentifierInfo(RawToken);
3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (RawToken.getIdentifierInfo() != nullptr) {
3888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        switch (RawToken.getIdentifierInfo()->getPPKeywordID()) {
3898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_include:
3908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_include_next:
3918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_import: {
3928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite,
3938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              Line);
3946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            if (FileId != PP.getPredefinesFileID())
3956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines              WriteLineInfo(FileName, Line - 1, FileType, EOL, "");
39603409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            StringRef LineInfoExtra;
3978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            if (const FileChange *Change = FindFileChangeLocation(
3988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                HashToken.getLocation())) {
39903409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              if (Change->Mod) {
40003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                WriteImplicitModuleImport(Change->Mod, EOL);
40103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis
40203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              // else now include and recursively process the file
40303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              } else if (Process(Change->Id, Change->FileType)) {
4048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // and set lineinfo back to this file, if the nested one was
4058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // actually included
4068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // `2' indicates returning to a file (after having included
4078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // another file.
40803409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                LineInfoExtra = " 2";
409507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis              }
41003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            }
41103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            // fix up lineinfo (since commented out directive changed line
41203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            // numbers) for inclusions that were skipped due to header guards
41303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            WriteLineInfo(FileName, Line, FileType, EOL, LineInfoExtra);
4148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
4158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          }
4168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_pragma: {
4178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            StringRef Identifier = NextIdentifierName(RawLex, RawToken);
4188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            if (Identifier == "clang" || Identifier == "GCC") {
4198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              if (NextIdentifierName(RawLex, RawToken) == "system_header") {
4208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // keep the directive in, commented out
4218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                CommentOutDirective(RawLex, HashToken, FromFile, EOL,
4228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                  NextToWrite, Line);
4238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // update our own type
4248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                FileType = SM.getFileCharacteristic(RawToken.getLocation());
4258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                WriteLineInfo(FileName, Line, FileType, EOL);
4268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              }
4278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            } else if (Identifier == "once") {
4288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              // keep the directive in, commented out
4298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              CommentOutDirective(RawLex, HashToken, FromFile, EOL,
4308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                NextToWrite, Line);
4318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              WriteLineInfo(FileName, Line, FileType, EOL);
4328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            }
4338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
4348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          }
435596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer          case tok::pp_if:
436ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak          case tok::pp_elif: {
437ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            bool elif = (RawToken.getIdentifierInfo()->getPPKeywordID() ==
438ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                         tok::pp_elif);
439596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            // Rewrite special builtin macros to avoid pulling in host details.
440596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            do {
441596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              // Walk over the directive.
442596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              RawLex.LexFromRawLexer(RawToken);
443596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              if (RawToken.is(tok::raw_identifier))
444596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                PP.LookUpIdentifierInfo(RawToken);
445596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
446596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              if (RawToken.is(tok::identifier)) {
447596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                bool HasFile;
448596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                SourceLocation Loc = RawToken.getLocation();
449596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
450596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // Rewrite __has_include(x)
451596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
4526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                  if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
4536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                        HasFile))
454596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    continue;
455596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  // Rewrite __has_include_next(x)
456596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                } else if (RawToken.getIdentifierInfo()->isStr(
457596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                               "__has_include_next")) {
458596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  const DirectoryLookup *Lookup = PP.GetCurDirLookup();
459596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  if (Lookup)
460596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    ++Lookup;
461596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
462596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken,
463596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                        HasFile))
464596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    continue;
465596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                } else {
466596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  continue;
467596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                }
468596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // Replace the macro with (0) or (1), followed by the commented
469596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // out macro for reference.
470596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  EOL, Line, false);
472596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OS << '(' << (int) HasFile << ")/*";
473596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OutputContentUpTo(FromFile, NextToWrite,
474596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  SM.getFileOffset(RawToken.getLocation()) +
475596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  RawToken.getLength(),
476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  EOL, Line, false);
477596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OS << "*/";
478596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              }
479596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            } while (RawToken.isNot(tok::eod));
480ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            if (elif) {
481ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak              OutputContentUpTo(FromFile, NextToWrite,
482ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                                SM.getFileOffset(RawToken.getLocation()) +
483ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                                    RawToken.getLength(),
484ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                                EOL, Line, /*EnsureNewLine*/ true);
485ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak              WriteLineInfo(FileName, Line, FileType, EOL);
486ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            }
487596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            break;
488ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak          }
489ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak          case tok::pp_endif:
490ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak          case tok::pp_else: {
491ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            // We surround every #include by #if 0 to comment it out, but that
492ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            // changes line numbers. These are fixed up right after that, but
493ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            // the whole #include could be inside a preprocessor conditional
494ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            // that is not processed. So it is necessary to fix the line
495ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            // numbers one the next line after each #else/#endif as well.
496ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            RawLex.SetKeepWhitespaceMode(true);
497ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            do {
498ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak              RawLex.LexFromRawLexer(RawToken);
499ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            } while (RawToken.isNot(tok::eod) && RawToken.isNot(tok::eof));
500ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            OutputContentUpTo(
501ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                FromFile, NextToWrite,
502ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                SM.getFileOffset(RawToken.getLocation()) + RawToken.getLength(),
503ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak                EOL, Line, /*EnsureNewLine*/ true);
504ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            WriteLineInfo(FileName, Line, FileType, EOL);
505ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak            RawLex.SetKeepWhitespaceMode(false);
506ce6af1189fb8f6d2a6fa083cff84a796c8377504Lubos Lunak          }
5078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          default:
5088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
5098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        }
5108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      }
5118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.setParsingPreprocessorDirective(false);
5128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    }
5138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    RawLex.LexFromRawLexer(RawToken);
5148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
5158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
516b18840ddd6aa472bbf78ab9de59159eb128fb6a9Argyrios Kyrtzidis    SM.getFileOffset(SM.getLocForEndOfFile(FileId)), EOL, Line,
5178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    /*EnsureNewline*/true);
5188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return true;
5198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
5208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
52160ad16b7e24cdb88c577c107b69da85458000858David Blaikie/// InclusionRewriterInInput - Implement -frewrite-includes mode.
5228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
5238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                   const PreprocessorOutputOptions &Opts) {
5248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  SourceManager &SM = PP.getSourceManager();
5258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS,
5268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                                     Opts.ShowLineMarkers);
5278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.addPPCallbacks(Rewrite);
5286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PP.IgnorePragmas();
5298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
5308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // First let the preprocessor process the entire file and call callbacks.
5318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // Callbacks will record which #include's were actually performed.
5328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.EnterMainSourceFile();
5338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token Tok;
5348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // Only preprocessor directives matter here, so disable macro expansion
5358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // everywhere else as an optimization.
5368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // TODO: It would be even faster if the preprocessor could be switched
5378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // to a mode where it would parse only preprocessor directives and comments,
5388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // nothing else matters for parsing or processing.
5398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.SetMacroExpansionOnlyInDirectives();
5408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  do {
5418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    PP.Lex(Tok);
5428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } while (Tok.isNot(tok::eof));
543e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID()));
544e9512e2c275bf24295202443452da314fb77270fArgyrios Kyrtzidis  Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User);
5458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
5468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS->flush();
5478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
548