FrontendActions.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //===--- FrontendActions.cpp ----------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/Frontend/FrontendActions.h"
  10. #include "clang/AST/ASTConsumer.h"
  11. #include "clang/Lex/Preprocessor.h"
  12. #include "clang/Parse/Parser.h"
  13. #include "clang/Basic/FileManager.h"
  14. #include "clang/Frontend/AnalysisConsumer.h"
  15. #include "clang/Frontend/ASTConsumers.h"
  16. #include "clang/Frontend/ASTUnit.h"
  17. #include "clang/Frontend/CompilerInstance.h"
  18. #include "clang/Frontend/FixItRewriter.h"
  19. #include "clang/Frontend/FrontendDiagnostic.h"
  20. #include "clang/Frontend/Utils.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. using namespace clang;
  23. //===----------------------------------------------------------------------===//
  24. // Custom Actions
  25. //===----------------------------------------------------------------------===//
  26. ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
  27. llvm::StringRef InFile) {
  28. return new ASTConsumer();
  29. }
  30. void InitOnlyAction::ExecuteAction() {
  31. }
  32. //===----------------------------------------------------------------------===//
  33. // AST Consumer Actions
  34. //===----------------------------------------------------------------------===//
  35. ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
  36. llvm::StringRef InFile) {
  37. return CreateAnalysisConsumer(CI.getPreprocessor(),
  38. CI.getFrontendOpts().OutputFile,
  39. CI.getAnalyzerOpts());
  40. }
  41. ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
  42. llvm::StringRef InFile) {
  43. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  44. return CreateASTPrinter(OS);
  45. return 0;
  46. }
  47. ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
  48. llvm::StringRef InFile) {
  49. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
  50. return CreateASTPrinterXML(OS);
  51. return 0;
  52. }
  53. ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
  54. llvm::StringRef InFile) {
  55. return CreateASTDumper();
  56. }
  57. ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
  58. llvm::StringRef InFile) {
  59. return CreateASTViewer();
  60. }
  61. ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
  62. llvm::StringRef InFile) {
  63. return CreateDeclContextPrinter();
  64. }
  65. ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
  66. llvm::StringRef InFile) {
  67. const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
  68. if (CI.getFrontendOpts().RelocatablePCH &&
  69. Sysroot.empty()) {
  70. CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
  71. return 0;
  72. }
  73. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
  74. if (!OS)
  75. return 0;
  76. if (CI.getFrontendOpts().RelocatablePCH)
  77. return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
  78. return CreatePCHGenerator(CI.getPreprocessor(), OS);
  79. }
  80. ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
  81. llvm::StringRef InFile) {
  82. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  83. return CreateHTMLPrinter(OS, CI.getPreprocessor());
  84. return 0;
  85. }
  86. ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
  87. llvm::StringRef InFile) {
  88. return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
  89. }
  90. FixItAction::FixItAction() {}
  91. FixItAction::~FixItAction() {}
  92. ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
  93. llvm::StringRef InFile) {
  94. return new ASTConsumer();
  95. }
  96. /// AddFixItLocations - Add any individual user specified "fix-it" locations,
  97. /// and return true on success.
  98. static bool AddFixItLocations(CompilerInstance &CI,
  99. FixItRewriter &FixItRewrite) {
  100. const std::vector<ParsedSourceLocation> &Locs =
  101. CI.getFrontendOpts().FixItLocations;
  102. for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
  103. const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
  104. if (!File) {
  105. CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
  106. << Locs[i].FileName;
  107. return false;
  108. }
  109. RequestedSourceLocation Requested;
  110. Requested.File = File;
  111. Requested.Line = Locs[i].Line;
  112. Requested.Column = Locs[i].Column;
  113. FixItRewrite.addFixItLocation(Requested);
  114. }
  115. return true;
  116. }
  117. bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
  118. llvm::StringRef Filename) {
  119. Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
  120. CI.getLangOpts()));
  121. if (!AddFixItLocations(CI, *Rewriter))
  122. return false;
  123. return true;
  124. }
  125. void FixItAction::EndSourceFileAction() {
  126. const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  127. Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
  128. }
  129. ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
  130. llvm::StringRef InFile) {
  131. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
  132. return CreateObjCRewriter(InFile, OS,
  133. CI.getDiagnostics(), CI.getLangOpts(),
  134. CI.getDiagnosticOpts().NoRewriteMacros);
  135. return 0;
  136. }
  137. ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
  138. llvm::StringRef InFile) {
  139. return new ASTConsumer();
  140. }
  141. //===----------------------------------------------------------------------===//
  142. // Preprocessor Actions
  143. //===----------------------------------------------------------------------===//
  144. void DumpRawTokensAction::ExecuteAction() {
  145. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  146. SourceManager &SM = PP.getSourceManager();
  147. // Start lexing the specified input file.
  148. const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
  149. Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
  150. RawLex.SetKeepWhitespaceMode(true);
  151. Token RawTok;
  152. RawLex.LexFromRawLexer(RawTok);
  153. while (RawTok.isNot(tok::eof)) {
  154. PP.DumpToken(RawTok, true);
  155. llvm::errs() << "\n";
  156. RawLex.LexFromRawLexer(RawTok);
  157. }
  158. }
  159. void DumpTokensAction::ExecuteAction() {
  160. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  161. // Start preprocessing the specified input file.
  162. Token Tok;
  163. if (PP.EnterMainSourceFile())
  164. return;
  165. do {
  166. PP.Lex(Tok);
  167. PP.DumpToken(Tok, true);
  168. llvm::errs() << "\n";
  169. } while (Tok.isNot(tok::eof));
  170. }
  171. void GeneratePTHAction::ExecuteAction() {
  172. CompilerInstance &CI = getCompilerInstance();
  173. if (CI.getFrontendOpts().OutputFile.empty() ||
  174. CI.getFrontendOpts().OutputFile == "-") {
  175. // FIXME: Don't fail this way.
  176. // FIXME: Verify that we can actually seek in the given file.
  177. llvm::report_fatal_error("PTH requires a seekable file for output!");
  178. }
  179. llvm::raw_fd_ostream *OS =
  180. CI.createDefaultOutputFile(true, getCurrentFile());
  181. if (!OS) return;
  182. CacheTokens(CI.getPreprocessor(), OS);
  183. }
  184. void ParseOnlyAction::ExecuteAction() {
  185. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  186. llvm::OwningPtr<Action> PA(new MinimalAction(PP));
  187. Parser P(PP, *PA);
  188. if (PP.EnterMainSourceFile())
  189. return;
  190. P.ParseTranslationUnit();
  191. }
  192. void PreprocessOnlyAction::ExecuteAction() {
  193. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  194. Token Tok;
  195. // Start parsing the specified input file.
  196. if (PP.EnterMainSourceFile())
  197. return;
  198. do {
  199. PP.Lex(Tok);
  200. } while (Tok.isNot(tok::eof));
  201. }
  202. void PrintParseAction::ExecuteAction() {
  203. CompilerInstance &CI = getCompilerInstance();
  204. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  205. llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  206. if (!OS) return;
  207. llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
  208. Parser P(PP, *PA);
  209. if (PP.EnterMainSourceFile())
  210. return;
  211. P.ParseTranslationUnit();
  212. }
  213. void PrintPreprocessedAction::ExecuteAction() {
  214. CompilerInstance &CI = getCompilerInstance();
  215. // Output file needs to be set to 'Binary', to avoid converting Unix style
  216. // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
  217. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  218. if (!OS) return;
  219. DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
  220. CI.getPreprocessorOutputOpts());
  221. }
  222. void RewriteMacrosAction::ExecuteAction() {
  223. CompilerInstance &CI = getCompilerInstance();
  224. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  225. if (!OS) return;
  226. RewriteMacrosInInput(CI.getPreprocessor(), OS);
  227. }
  228. void RewriteTestAction::ExecuteAction() {
  229. CompilerInstance &CI = getCompilerInstance();
  230. llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  231. if (!OS) return;
  232. DoRewriteTest(CI.getPreprocessor(), OS);
  233. }