InclusionRewriter.cpp revision b18840ddd6aa472bbf78ab9de59159eb128fb6a9
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"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h"
20596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer#include "llvm/ADT/SmallString.h"
218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie#include "llvm/Support/raw_ostream.h"
228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing namespace clang;
248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing namespace llvm;
258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikienamespace {
278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieclass InclusionRewriter : public PPCallbacks {
298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// Information about which #includes were actually performed,
308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// created by preprocessor callbacks.
318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  struct FileChange {
3203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    const Module *Mod;
338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SourceLocation From;
348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    FileID Id;
358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SrcMgr::CharacteristicKind FileType;
3603409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    FileChange(SourceLocation From, const Module *Mod) : Mod(Mod), From(From) {
378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    }
388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  };
3949fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  Preprocessor &PP; ///< Used to find inclusion directives.
4049fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  SourceManager &SM; ///< Used to read and manage source files.
4149fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  raw_ostream &OS; ///< The destination stream for rewritten contents.
4249fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  bool ShowLineMarkers; ///< Show #line markers.
4349fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko  bool UseLineDirective; ///< Use of line directives or line markers.
448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  typedef std::map<unsigned, FileChange> FileChangeMap;
45959dc8475fc20ce8c3fd55021cb9f02a531cddc5Dmitri Gribenko  FileChangeMap FileChanges; ///< Tracks which files were included where.
468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// Used transitively for building up the FileChanges mapping over the
478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  /// various \c PPCallbacks callbacks.
488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChangeMap::iterator LastInsertedFileChange;
498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiepublic:
508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers);
518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType);
528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieprivate:
538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           SrcMgr::CharacteristicKind FileType,
558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           FileID PrevFID);
568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  virtual void FileSkipped(const FileEntry &ParentFile,
578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           const Token &FilenameTok,
588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                           SrcMgr::CharacteristicKind FileType);
598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  virtual void InclusionDirective(SourceLocation HashLoc,
608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                  const Token &IncludeTok,
618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                  StringRef FileName,
628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                  bool IsAngled,
63da313592441db36cf4b06be97c4bcc238ee6fa9cArgyrios Kyrtzidis                                  CharSourceRange FilenameRange,
648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                  const FileEntry *File,
658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                  StringRef SearchPath,
66f8afcffe6a0213760b64c211812b1750e1e1e967Argyrios Kyrtzidis                                  StringRef RelativePath,
67f8afcffe6a0213760b64c211812b1750e1e1e967Argyrios Kyrtzidis                                  const Module *Imported);
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,
758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                         bool EnsureNewline = false);
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)
918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    : PP(PP), SM(PP.getSourceManager()), OS(OS),
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) {
1088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    OS << "#line" << ' ' << Line << ' ' << '"' << Filename << '"';
1098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } else {
1108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // Use GNU linemarkers as described here:
1118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
1128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    OS << '#' << ' ' << Line << ' ' << '"' << Filename << '"';
1138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (!Extra.empty())
1148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << Extra;
1158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (FileType == SrcMgr::C_System)
1168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // "`3' This indicates that the following text comes from a system header
1178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // file, so certain warnings should be suppressed."
1188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << " 3";
1198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    else if (FileType == SrcMgr::C_ExternCSystem)
1208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // as above for `3', plus "`4' This indicates that the following text
1218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      // should be treated as being wrapped in an implicit extern "C" block."
1228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << " 3 4";
1238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
1248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS << EOL;
1258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
12703409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidisvoid InclusionRewriter::WriteImplicitModuleImport(const Module *Mod,
12803409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                                                  StringRef EOL) {
12903409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis  OS << "@import " << Mod->getFullModuleName() << ";"
13003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis     << " /* clang -frewrite-includes: implicit import */" << EOL;
13103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis}
13203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis
1338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// FileChanged - Whenever the preprocessor enters or exits a #include file
1348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// it invokes this handler.
1358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::FileChanged(SourceLocation Loc,
1368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    FileChangeReason Reason,
1378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    SrcMgr::CharacteristicKind NewFileType,
1388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    FileID) {
1398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Reason != EnterFile)
1408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (LastInsertedFileChange == FileChanges.end())
1428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    // we didn't reach this file (eg: the main file) via an inclusion directive
1438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange->second.Id = FullSourceLoc(Loc, SM).getFileID();
1458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange->second.FileType = NewFileType;
1468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange = FileChanges.end();
1478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Called whenever an inclusion is skipped due to canonical header protection
1508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// macros.
1518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::FileSkipped(const FileEntry &/*ParentFile*/,
1528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    const Token &/*FilenameTok*/,
1538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                    SrcMgr::CharacteristicKind /*FileType*/) {
1548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(LastInsertedFileChange != FileChanges.end() && "A file, that wasn't "
1558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    "found via an inclusion directive, was skipped");
1568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChanges.erase(LastInsertedFileChange);
1578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  LastInsertedFileChange = FileChanges.end();
1588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// This should be called whenever the preprocessor encounters include
1618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// directives. It does not say whether the file has been included, but it
1628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// provides more information about the directive (hash location instead
1638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// of location inside the included file). It is assumed that the matching
1648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// FileChanged() or FileSkipped() is called after this.
1658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
1668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           const Token &/*IncludeTok*/,
1678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           StringRef /*FileName*/,
1688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           bool /*IsAngled*/,
169da313592441db36cf4b06be97c4bcc238ee6fa9cArgyrios Kyrtzidis                                           CharSourceRange /*FilenameRange*/,
1708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           const FileEntry * /*File*/,
1718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                           StringRef /*SearchPath*/,
172f8afcffe6a0213760b64c211812b1750e1e1e967Argyrios Kyrtzidis                                           StringRef /*RelativePath*/,
17303409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                                           const Module *Imported) {
1748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
1758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    "directive was found before the previous one was processed");
1768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
17703409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc, Imported)));
1788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  assert(p.second && "Unexpected revisitation of the same include directive");
17903409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis  if (!Imported)
18003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis    LastInsertedFileChange = p.first;
1818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Simple lookup for a SourceLocation (specifically one denoting the hash in
1848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// an inclusion directive) in the map of inclusion information, FileChanges.
1858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieconst InclusionRewriter::FileChange *
1868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieInclusionRewriter::FindFileChangeLocation(SourceLocation Loc) const {
1878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  FileChangeMap::const_iterator I = FileChanges.find(Loc.getRawEncoding());
1888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (I != FileChanges.end())
1898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return &I->second;
1908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return NULL;
1918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
1928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Detect the likely line ending style of \p FromFile by examining the first
1948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// newline found within it.
1958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiestatic StringRef DetectEOL(const MemoryBuffer &FromFile) {
1968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // detect what line endings the file uses, so that added content does not mix
1978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // the style
1988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const char *Pos = strchr(FromFile.getBufferStart(), '\n');
1998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Pos == NULL)
2008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\n";
2018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
2028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\n\r";
2038c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r')
2048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return "\r\n";
2058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return "\n";
2068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
2098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// \p WriteTo - 1.
2108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
2118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          unsigned &WriteFrom, unsigned WriteTo,
2128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          StringRef EOL, int &Line,
2138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                          bool EnsureNewline) {
2148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (WriteTo <= WriteFrom)
2158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
2168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS.write(FromFile.getBufferStart() + WriteFrom, WriteTo - WriteFrom);
2178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // count lines manually, it's faster than getPresumedLoc()
2183159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer  Line += std::count(FromFile.getBufferStart() + WriteFrom,
2193159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer                     FromFile.getBufferStart() + WriteTo, '\n');
2208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (EnsureNewline) {
2218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    char LastChar = FromFile.getBufferStart()[WriteTo - 1];
2228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (LastChar != '\n' && LastChar != '\r')
2238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      OS << EOL;
2248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
2258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  WriteFrom = WriteTo;
2268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Print characters from \p FromFile starting at \p NextToWrite up until the
2298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// inclusion directive at \p StartToken, then print out the inclusion
2308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// inclusion directive disabled by a #if directive, updating \p NextToWrite
2318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// and \p Line to track the number of source lines visited and the progress
2328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// through the \p FromFile buffer.
2338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
2348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            const Token &StartToken,
2358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            const MemoryBuffer &FromFile,
2368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            StringRef EOL,
2378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                            unsigned &NextToWrite, int &Line) {
2388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
2398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SM.getFileOffset(StartToken.getLocation()), EOL, Line);
2408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token DirectiveToken;
2418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  do {
2428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    DirectiveLex.LexFromRawLexer(DirectiveToken);
2438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
24460ad16b7e24cdb88c577c107b69da85458000858David Blaikie  OS << "#if 0 /* expanded by -frewrite-includes */" << EOL;
2458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
2468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    SM.getFileOffset(DirectiveToken.getLocation()) + DirectiveToken.getLength(),
2478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    EOL, Line);
24860ad16b7e24cdb88c577c107b69da85458000858David Blaikie  OS << "#endif /* expanded by -frewrite-includes */" << EOL;
2498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
2518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Find the next identifier in the pragma directive specified by \p RawToken.
2528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieStringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex,
2538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                                Token &RawToken) {
2548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.LexFromRawLexer(RawToken);
2558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (RawToken.is(tok::raw_identifier))
2568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    PP.LookUpIdentifierInfo(RawToken);
2578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (RawToken.is(tok::identifier))
2588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return RawToken.getIdentifierInfo()->getName();
2598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return StringRef();
2608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
2618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
262596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer// Expand __has_include and __has_include_next if possible. If there's no
263596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer// definitive answer return false.
264596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramerbool InclusionRewriter::HandleHasInclude(
265596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
266596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    bool &FileExists) {
267596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Lex the opening paren.
268596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
269596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.isNot(tok::l_paren))
270596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    return false;
271596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
272596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
273596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
274596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  SmallString<128> FilenameBuffer;
275596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  StringRef Filename;
276596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Since the raw lexer doesn't give us angle_literals we have to parse them
277596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // ourselves.
278596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // FIXME: What to do if the file name is a macro?
279596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.is(tok::less)) {
280596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    RawLex.LexFromRawLexer(Tok);
281596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
282596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FilenameBuffer += '<';
283596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    do {
284596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Tok.is(tok::eod)) // Sanity check.
285596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        return false;
286596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
287596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Tok.is(tok::raw_identifier))
288596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        PP.LookUpIdentifierInfo(Tok);
289596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
290596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      // Get the string piece.
291596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      SmallVector<char, 128> TmpBuffer;
292596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      bool Invalid = false;
293596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid);
294596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (Invalid)
295596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer        return false;
296596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
297596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      FilenameBuffer += TmpName;
298596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
299596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      RawLex.LexFromRawLexer(Tok);
300596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    } while (Tok.isNot(tok::greater));
301596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
302596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    FilenameBuffer += '>';
303596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    Filename = FilenameBuffer;
304596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  } else {
305596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    if (Tok.isNot(tok::string_literal))
306596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      return false;
307596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
308596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    bool Invalid = false;
309596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
310596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    if (Invalid)
311596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      return false;
312596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  }
313596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
314596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Lex the closing paren.
315596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  RawLex.LexFromRawLexer(Tok);
316596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  if (Tok.isNot(tok::r_paren))
317596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer    return false;
318596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
319596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // Now ask HeaderInfo if it knows about the header.
320596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  // FIXME: Subframeworks aren't handled here. Do we care?
321596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
322596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  const DirectoryLookup *CurDir;
323596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
324596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      Filename, isAngled, 0, CurDir,
325596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      PP.getSourceManager().getFileEntryForID(FileId), 0, 0, 0, false);
326596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
327596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  FileExists = File != 0;
328596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer  return true;
329596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer}
330596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
3318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// Use a raw lexer to analyze \p FileId, inccrementally copying parts of it
3328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie/// and including content of included files recursively.
3338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiebool InclusionRewriter::Process(FileID FileId,
3348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                SrcMgr::CharacteristicKind FileType)
3358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie{
3368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  bool Invalid;
3378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
338bae2b31822e3c2139b5f8fbb127e4c5674cce6dbDavid Blaikie  if (Invalid) // invalid inclusion
339507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis    return false;
3408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  const char *FileName = FromFile.getBufferIdentifier();
3418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
3428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.SetCommentRetentionState(false);
3438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  StringRef EOL = DetectEOL(FromFile);
3458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // Per the GNU docs: "1" indicates the start of a new file.
3478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  WriteLineInfo(FileName, 1, FileType, EOL, " 1");
3488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (SM.getFileIDSize(FileId) == 0)
350507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis    return false;
3518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // The next byte to be copied from the source file
3538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  unsigned NextToWrite = 0;
3548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  int Line = 1; // The current input file line number.
3558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token RawToken;
3578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  RawLex.LexFromRawLexer(RawToken);
3588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
3598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // TODO: Consider adding a switch that strips possibly unimportant content,
3608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // such as comments, to reduce the size of repro files.
3618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  while (RawToken.isNot(tok::eof)) {
3628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    if (RawToken.is(tok::hash) && RawToken.isAtStartOfLine()) {
3638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.setParsingPreprocessorDirective(true);
3648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      Token HashToken = RawToken;
3658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.LexFromRawLexer(RawToken);
3668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      if (RawToken.is(tok::raw_identifier))
3678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        PP.LookUpIdentifierInfo(RawToken);
368596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer      if (RawToken.is(tok::identifier) || RawToken.is(tok::kw_if)) {
3698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        switch (RawToken.getIdentifierInfo()->getPPKeywordID()) {
3708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_include:
3718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_include_next:
3728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_import: {
3738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite,
3748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              Line);
37503409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            StringRef LineInfoExtra;
3768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            if (const FileChange *Change = FindFileChangeLocation(
3778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                HashToken.getLocation())) {
37803409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              if (Change->Mod) {
37903409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                WriteImplicitModuleImport(Change->Mod, EOL);
38003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis
38103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              // else now include and recursively process the file
38203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis              } else if (Process(Change->Id, Change->FileType)) {
3838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // and set lineinfo back to this file, if the nested one was
3848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // actually included
3858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // `2' indicates returning to a file (after having included
3868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // another file.
38703409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis                LineInfoExtra = " 2";
388507d496e18fb7bf54e4cb8f79df56941f93f1edaArgyrios Kyrtzidis              }
38903409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            }
39003409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            // fix up lineinfo (since commented out directive changed line
39103409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            // numbers) for inclusions that were skipped due to header guards
39203409967bd9860ffb2ff6b38126e04493c55567fArgyrios Kyrtzidis            WriteLineInfo(FileName, Line, FileType, EOL, LineInfoExtra);
3938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
3948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          }
3958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          case tok::pp_pragma: {
3968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            StringRef Identifier = NextIdentifierName(RawLex, RawToken);
3978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            if (Identifier == "clang" || Identifier == "GCC") {
3988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              if (NextIdentifierName(RawLex, RawToken) == "system_header") {
3998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // keep the directive in, commented out
4008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                CommentOutDirective(RawLex, HashToken, FromFile, EOL,
4018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                  NextToWrite, Line);
4028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                // update our own type
4038c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                FileType = SM.getFileCharacteristic(RawToken.getLocation());
4048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                WriteLineInfo(FileName, Line, FileType, EOL);
4058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              }
4068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            } else if (Identifier == "once") {
4078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              // keep the directive in, commented out
4088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              CommentOutDirective(RawLex, HashToken, FromFile, EOL,
4098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                NextToWrite, Line);
4108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie              WriteLineInfo(FileName, Line, FileType, EOL);
4118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            }
4128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
4138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          }
414596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer          case tok::pp_if:
415596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer          case tok::pp_elif:
416596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            // Rewrite special builtin macros to avoid pulling in host details.
417596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            do {
418596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              // Walk over the directive.
419596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              RawLex.LexFromRawLexer(RawToken);
420596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              if (RawToken.is(tok::raw_identifier))
421596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                PP.LookUpIdentifierInfo(RawToken);
422596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
423596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              if (RawToken.is(tok::identifier)) {
424596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                bool HasFile;
425596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                SourceLocation Loc = RawToken.getLocation();
426596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
427596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // Rewrite __has_include(x)
428596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
429596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  if (!HandleHasInclude(FileId, RawLex, 0, RawToken, HasFile))
430596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    continue;
431596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  // Rewrite __has_include_next(x)
432596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                } else if (RawToken.getIdentifierInfo()->isStr(
433596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                               "__has_include_next")) {
434596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  const DirectoryLookup *Lookup = PP.GetCurDirLookup();
435596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  if (Lookup)
436596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    ++Lookup;
437596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
438596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken,
439596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                        HasFile))
440596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                    continue;
441596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                } else {
442596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                  continue;
443596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                }
444596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // Replace the macro with (0) or (1), followed by the commented
445596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                // out macro for reference.
446596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
447596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  EOL, Line);
448596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OS << '(' << (int) HasFile << ")/*";
449596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OutputContentUpTo(FromFile, NextToWrite,
450596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  SM.getFileOffset(RawToken.getLocation()) +
451596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  RawToken.getLength(),
452596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                                  EOL, Line);
453596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer                OS << "*/";
454596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer              }
455596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            } while (RawToken.isNot(tok::eod));
456596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer
457596eea7cc26979c952a0b177d024787a99b299dfBenjamin Kramer            break;
4588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie          default:
4598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie            break;
4608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie        }
4618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      }
4628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      RawLex.setParsingPreprocessorDirective(false);
4638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    }
4648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    RawLex.LexFromRawLexer(RawToken);
4658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  }
4668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OutputContentUpTo(FromFile, NextToWrite,
467b18840ddd6aa472bbf78ab9de59159eb128fb6a9Argyrios Kyrtzidis    SM.getFileOffset(SM.getLocForEndOfFile(FileId)), EOL, Line,
4688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    /*EnsureNewline*/true);
4698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  return true;
4708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
4718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
47260ad16b7e24cdb88c577c107b69da85458000858David Blaikie/// InclusionRewriterInInput - Implement -frewrite-includes mode.
4738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikievoid clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
4748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                   const PreprocessorOutputOptions &Opts) {
4758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  SourceManager &SM = PP.getSourceManager();
4768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS,
4778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie                                                     Opts.ShowLineMarkers);
4788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.addPPCallbacks(Rewrite);
4798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
4808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // First let the preprocessor process the entire file and call callbacks.
4818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // Callbacks will record which #include's were actually performed.
4828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.EnterMainSourceFile();
4838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Token Tok;
4848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // Only preprocessor directives matter here, so disable macro expansion
4858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // everywhere else as an optimization.
4868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // TODO: It would be even faster if the preprocessor could be switched
4878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // to a mode where it would parse only preprocessor directives and comments,
4888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  // nothing else matters for parsing or processing.
4898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  PP.SetMacroExpansionOnlyInDirectives();
4908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  do {
4918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    PP.Lex(Tok);
4928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  } while (Tok.isNot(tok::eof));
4938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User);
4948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  OS->flush();
4958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie}
496