FrontendActions.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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/ADT/OwningPtr.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. using namespace clang;
  24. //===----------------------------------------------------------------------===//
  25. // Custom Actions
  26. //===----------------------------------------------------------------------===//
  27. ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
  28. llvm::StringRef InFile) {
  29. return new ASTConsumer();
  30. }
  31. void InitOnlyAction::ExecuteAction() {
  32. }
  33. //===----------------------------------------------------------------------===//
  34. // AST Consumer Actions
  35. //===----------------------------------------------------------------------===//
  36. ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
  37. llvm::StringRef InFile) {
  38. return CreateAnalysisConsumer(CI.getPreprocessor(),
  39. CI.getFrontendOpts().OutputFile,
  40. CI.getAnalyzerOpts());
  41. }
  42. ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
  43. llvm::StringRef InFile) {
  44. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  45. return CreateASTPrinter(OS);
  46. return 0;
  47. }
  48. ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
  49. llvm::StringRef InFile) {
  50. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
  51. return CreateASTPrinterXML(OS);
  52. return 0;
  53. }
  54. ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
  55. llvm::StringRef InFile) {
  56. return CreateASTDumper();
  57. }
  58. ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
  59. llvm::StringRef InFile) {
  60. return CreateASTViewer();
  61. }
  62. ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
  63. llvm::StringRef InFile) {
  64. return CreateDeclContextPrinter();
  65. }
  66. ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
  67. llvm::StringRef InFile) {
  68. const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
  69. if (CI.getFrontendOpts().RelocatablePCH &&
  70. Sysroot.empty()) {
  71. CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
  72. return 0;
  73. }
  74. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
  75. if (!OS)
  76. return 0;
  77. if (CI.getFrontendOpts().RelocatablePCH)
  78. return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
  79. return CreatePCHGenerator(CI.getPreprocessor(), OS);
  80. }
  81. ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
  82. llvm::StringRef InFile) {
  83. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  84. return CreateHTMLPrinter(OS, CI.getPreprocessor());
  85. return 0;
  86. }
  87. ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
  88. llvm::StringRef InFile) {
  89. return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
  90. }
  91. FixItAction::FixItAction() {}
  92. FixItAction::~FixItAction() {}
  93. ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
  94. llvm::StringRef InFile) {
  95. return new ASTConsumer();
  96. }
  97. class FixItActionSuffixInserter : public FixItPathRewriter {
  98. std::string NewSuffix;
  99. public:
  100. explicit FixItActionSuffixInserter(std::string NewSuffix)
  101. : NewSuffix(NewSuffix) {}
  102. std::string RewriteFilename(const std::string &Filename) {
  103. llvm::sys::Path Path(Filename);
  104. std::string Suffix = Path.getSuffix();
  105. Path.eraseSuffix();
  106. Path.appendSuffix(NewSuffix + "." + Suffix);
  107. return Path.c_str();
  108. }
  109. };
  110. bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
  111. llvm::StringRef Filename) {
  112. const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  113. if (!FEOpts.FixItSuffix.empty()) {
  114. PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix));
  115. } else {
  116. PathRewriter.reset();
  117. }
  118. Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
  119. CI.getLangOpts(), PathRewriter.get()));
  120. return true;
  121. }
  122. void FixItAction::EndSourceFileAction() {
  123. // Otherwise rewrite all files.
  124. Rewriter->WriteFixedFiles();
  125. }
  126. ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
  127. llvm::StringRef InFile) {
  128. if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
  129. return CreateObjCRewriter(InFile, OS,
  130. CI.getDiagnostics(), CI.getLangOpts(),
  131. CI.getDiagnosticOpts().NoRewriteMacros);
  132. return 0;
  133. }
  134. ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
  135. llvm::StringRef InFile) {
  136. return new ASTConsumer();
  137. }
  138. //===----------------------------------------------------------------------===//
  139. // Preprocessor Actions
  140. //===----------------------------------------------------------------------===//
  141. void DumpRawTokensAction::ExecuteAction() {
  142. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  143. SourceManager &SM = PP.getSourceManager();
  144. // Start lexing the specified input file.
  145. const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
  146. Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
  147. RawLex.SetKeepWhitespaceMode(true);
  148. Token RawTok;
  149. RawLex.LexFromRawLexer(RawTok);
  150. while (RawTok.isNot(tok::eof)) {
  151. PP.DumpToken(RawTok, true);
  152. llvm::errs() << "\n";
  153. RawLex.LexFromRawLexer(RawTok);
  154. }
  155. }
  156. void DumpTokensAction::ExecuteAction() {
  157. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  158. // Start preprocessing the specified input file.
  159. Token Tok;
  160. PP.EnterMainSourceFile();
  161. do {
  162. PP.Lex(Tok);
  163. PP.DumpToken(Tok, true);
  164. llvm::errs() << "\n";
  165. } while (Tok.isNot(tok::eof));
  166. }
  167. void GeneratePTHAction::ExecuteAction() {
  168. CompilerInstance &CI = getCompilerInstance();
  169. if (CI.getFrontendOpts().OutputFile.empty() ||
  170. CI.getFrontendOpts().OutputFile == "-") {
  171. // FIXME: Don't fail this way.
  172. // FIXME: Verify that we can actually seek in the given file.
  173. llvm::report_fatal_error("PTH requires a seekable file for output!");
  174. }
  175. llvm::raw_fd_ostream *OS =
  176. CI.createDefaultOutputFile(true, getCurrentFile());
  177. if (!OS) return;
  178. CacheTokens(CI.getPreprocessor(), OS);
  179. }
  180. void ParseOnlyAction::ExecuteAction() {
  181. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  182. llvm::OwningPtr<Action> PA(new MinimalAction(PP));
  183. Parser P(PP, *PA);
  184. PP.EnterMainSourceFile();
  185. P.ParseTranslationUnit();
  186. }
  187. void PreprocessOnlyAction::ExecuteAction() {
  188. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  189. Token Tok;
  190. // Start parsing the specified input file.
  191. PP.EnterMainSourceFile();
  192. do {
  193. PP.Lex(Tok);
  194. } while (Tok.isNot(tok::eof));
  195. }
  196. void PrintParseAction::ExecuteAction() {
  197. CompilerInstance &CI = getCompilerInstance();
  198. Preprocessor &PP = getCompilerInstance().getPreprocessor();
  199. llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  200. if (!OS) return;
  201. llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
  202. Parser P(PP, *PA);
  203. PP.EnterMainSourceFile();
  204. P.ParseTranslationUnit();
  205. }
  206. void PrintPreprocessedAction::ExecuteAction() {
  207. CompilerInstance &CI = getCompilerInstance();
  208. // Output file needs to be set to 'Binary', to avoid converting Unix style
  209. // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
  210. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  211. if (!OS) return;
  212. DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
  213. CI.getPreprocessorOutputOpts());
  214. }
  215. void RewriteMacrosAction::ExecuteAction() {
  216. CompilerInstance &CI = getCompilerInstance();
  217. llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  218. if (!OS) return;
  219. RewriteMacrosInInput(CI.getPreprocessor(), OS);
  220. }
  221. void RewriteTestAction::ExecuteAction() {
  222. CompilerInstance &CI = getCompilerInstance();
  223. llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  224. if (!OS) return;
  225. DoRewriteTest(CI.getPreprocessor(), OS);
  226. }