blob: 421d69d24308159469e36490a4edd959fd6fa4b9 [file] [log] [blame]
Daniel Dunbar8305d012009-11-14 10:42:46 +00001//===--- 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
10#include "clang/Frontend/FrontendActions.h"
11#include "clang/AST/ASTConsumer.h"
Daniel Dunbarc72cc502010-06-11 20:10:12 +000012#include "clang/Lex/Pragma.h"
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000013#include "clang/Lex/Preprocessor.h"
14#include "clang/Parse/Parser.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000015#include "clang/Basic/FileManager.h"
16#include "clang/Frontend/AnalysisConsumer.h"
17#include "clang/Frontend/ASTConsumers.h"
18#include "clang/Frontend/ASTUnit.h"
19#include "clang/Frontend/CompilerInstance.h"
20#include "clang/Frontend/FixItRewriter.h"
21#include "clang/Frontend/FrontendDiagnostic.h"
22#include "clang/Frontend/Utils.h"
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +000023#include "llvm/ADT/OwningPtr.h"
Daniel Dunbar8305d012009-11-14 10:42:46 +000024#include "llvm/Support/raw_ostream.h"
25using namespace clang;
26
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000027//===----------------------------------------------------------------------===//
Daniel Dunbar27585952010-03-19 19:44:04 +000028// Custom Actions
29//===----------------------------------------------------------------------===//
30
31ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
32 llvm::StringRef InFile) {
33 return new ASTConsumer();
34}
35
36void InitOnlyAction::ExecuteAction() {
37}
38
39//===----------------------------------------------------------------------===//
Daniel Dunbar5f3b9972009-11-14 10:42:57 +000040// AST Consumer Actions
41//===----------------------------------------------------------------------===//
42
Daniel Dunbar8305d012009-11-14 10:42:46 +000043ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
44 llvm::StringRef InFile) {
45 return CreateAnalysisConsumer(CI.getPreprocessor(),
46 CI.getFrontendOpts().OutputFile,
47 CI.getAnalyzerOpts());
48}
49
50ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
51 llvm::StringRef InFile) {
Daniel Dunbar36043592009-12-03 09:13:30 +000052 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
53 return CreateASTPrinter(OS);
54 return 0;
Daniel Dunbar8305d012009-11-14 10:42:46 +000055}
56
57ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
58 llvm::StringRef InFile) {
Daniel Dunbar36043592009-12-03 09:13:30 +000059 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
60 return CreateASTPrinterXML(OS);
61 return 0;
Daniel Dunbar8305d012009-11-14 10:42:46 +000062}
63
64ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
65 llvm::StringRef InFile) {
66 return CreateASTDumper();
67}
68
69ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
70 llvm::StringRef InFile) {
71 return CreateASTViewer();
72}
73
74ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
75 llvm::StringRef InFile) {
76 return CreateDeclContextPrinter();
77}
78
Daniel Dunbar8305d012009-11-14 10:42:46 +000079ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
80 llvm::StringRef InFile) {
81 const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
82 if (CI.getFrontendOpts().RelocatablePCH &&
83 Sysroot.empty()) {
84 CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
85 return 0;
86 }
87
88 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
Daniel Dunbar36043592009-12-03 09:13:30 +000089 if (!OS)
90 return 0;
91
Daniel Dunbar8305d012009-11-14 10:42:46 +000092 if (CI.getFrontendOpts().RelocatablePCH)
93 return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
94
95 return CreatePCHGenerator(CI.getPreprocessor(), OS);
96}
97
98ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
99 llvm::StringRef InFile) {
Daniel Dunbar36043592009-12-03 09:13:30 +0000100 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
101 return CreateHTMLPrinter(OS, CI.getPreprocessor());
102 return 0;
Daniel Dunbar8305d012009-11-14 10:42:46 +0000103}
104
105ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
106 llvm::StringRef InFile) {
107 return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
108}
109
110FixItAction::FixItAction() {}
111FixItAction::~FixItAction() {}
112
113ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000114 llvm::StringRef InFile) {
Daniel Dunbar8305d012009-11-14 10:42:46 +0000115 return new ASTConsumer();
116}
117
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +0000118class FixItActionSuffixInserter : public FixItPathRewriter {
119 std::string NewSuffix;
Daniel Dunbar8305d012009-11-14 10:42:46 +0000120
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +0000121public:
122 explicit FixItActionSuffixInserter(std::string NewSuffix)
123 : NewSuffix(NewSuffix) {}
124
125 std::string RewriteFilename(const std::string &Filename) {
126 llvm::sys::Path Path(Filename);
127 std::string Suffix = Path.getSuffix();
128 Path.eraseSuffix();
129 Path.appendSuffix(NewSuffix + "." + Suffix);
130 return Path.c_str();
Daniel Dunbar8305d012009-11-14 10:42:46 +0000131 }
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +0000132};
Daniel Dunbar8305d012009-11-14 10:42:46 +0000133
134bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
135 llvm::StringRef Filename) {
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +0000136 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
137 if (!FEOpts.FixItSuffix.empty()) {
138 PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix));
139 } else {
140 PathRewriter.reset();
141 }
Daniel Dunbar8305d012009-11-14 10:42:46 +0000142 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
Nick Lewyckyba5f6ec2010-04-24 01:30:46 +0000143 CI.getLangOpts(), PathRewriter.get()));
Daniel Dunbar8305d012009-11-14 10:42:46 +0000144 return true;
145}
146
147void FixItAction::EndSourceFileAction() {
Nick Lewyckyd4a97a12010-04-15 06:46:58 +0000148 // Otherwise rewrite all files.
149 Rewriter->WriteFixedFiles();
Daniel Dunbar8305d012009-11-14 10:42:46 +0000150}
151
152ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
153 llvm::StringRef InFile) {
Daniel Dunbar36043592009-12-03 09:13:30 +0000154 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
155 return CreateObjCRewriter(InFile, OS,
156 CI.getDiagnostics(), CI.getLangOpts(),
157 CI.getDiagnosticOpts().NoRewriteMacros);
158 return 0;
Daniel Dunbar8305d012009-11-14 10:42:46 +0000159}
160
Daniel Dunbar8305d012009-11-14 10:42:46 +0000161ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
162 llvm::StringRef InFile) {
163 return new ASTConsumer();
164}
165
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000166//===----------------------------------------------------------------------===//
167// Preprocessor Actions
168//===----------------------------------------------------------------------===//
169
170void DumpRawTokensAction::ExecuteAction() {
171 Preprocessor &PP = getCompilerInstance().getPreprocessor();
172 SourceManager &SM = PP.getSourceManager();
173
174 // Start lexing the specified input file.
Chris Lattner6e290142009-11-30 04:18:44 +0000175 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
176 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000177 RawLex.SetKeepWhitespaceMode(true);
178
179 Token RawTok;
180 RawLex.LexFromRawLexer(RawTok);
181 while (RawTok.isNot(tok::eof)) {
182 PP.DumpToken(RawTok, true);
Daniel Dunbar33f57f82009-11-25 10:27:48 +0000183 llvm::errs() << "\n";
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000184 RawLex.LexFromRawLexer(RawTok);
185 }
186}
187
188void DumpTokensAction::ExecuteAction() {
189 Preprocessor &PP = getCompilerInstance().getPreprocessor();
190 // Start preprocessing the specified input file.
191 Token Tok;
Chris Lattnere127a0d2010-04-20 20:35:58 +0000192 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000193 do {
194 PP.Lex(Tok);
195 PP.DumpToken(Tok, true);
Daniel Dunbar33f57f82009-11-25 10:27:48 +0000196 llvm::errs() << "\n";
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000197 } while (Tok.isNot(tok::eof));
198}
199
200void GeneratePTHAction::ExecuteAction() {
201 CompilerInstance &CI = getCompilerInstance();
202 if (CI.getFrontendOpts().OutputFile.empty() ||
203 CI.getFrontendOpts().OutputFile == "-") {
204 // FIXME: Don't fail this way.
205 // FIXME: Verify that we can actually seek in the given file.
Chris Lattner83e7a782010-04-07 22:58:06 +0000206 llvm::report_fatal_error("PTH requires a seekable file for output!");
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000207 }
208 llvm::raw_fd_ostream *OS =
209 CI.createDefaultOutputFile(true, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000210 if (!OS) return;
211
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000212 CacheTokens(CI.getPreprocessor(), OS);
213}
214
215void ParseOnlyAction::ExecuteAction() {
216 Preprocessor &PP = getCompilerInstance().getPreprocessor();
217 llvm::OwningPtr<Action> PA(new MinimalAction(PP));
218
219 Parser P(PP, *PA);
Chris Lattnere127a0d2010-04-20 20:35:58 +0000220 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000221 P.ParseTranslationUnit();
222}
223
224void PreprocessOnlyAction::ExecuteAction() {
225 Preprocessor &PP = getCompilerInstance().getPreprocessor();
226
Daniel Dunbarc72cc502010-06-11 20:10:12 +0000227 // Ignore unknown pragmas.
228 PP.AddPragmaHandler(0, new EmptyPragmaHandler());
229
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000230 Token Tok;
231 // Start parsing the specified input file.
Chris Lattnere127a0d2010-04-20 20:35:58 +0000232 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000233 do {
234 PP.Lex(Tok);
235 } while (Tok.isNot(tok::eof));
236}
237
238void PrintParseAction::ExecuteAction() {
239 CompilerInstance &CI = getCompilerInstance();
240 Preprocessor &PP = getCompilerInstance().getPreprocessor();
241 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000242 if (!OS) return;
243
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000244 llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
245
246 Parser P(PP, *PA);
Chris Lattnere127a0d2010-04-20 20:35:58 +0000247 PP.EnterMainSourceFile();
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000248 P.ParseTranslationUnit();
249}
250
251void PrintPreprocessedAction::ExecuteAction() {
252 CompilerInstance &CI = getCompilerInstance();
Steve Naroffd57d7c02010-01-05 17:33:23 +0000253 // Output file needs to be set to 'Binary', to avoid converting Unix style
254 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
255 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000256 if (!OS) return;
257
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000258 DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
259 CI.getPreprocessorOutputOpts());
260}
261
262void RewriteMacrosAction::ExecuteAction() {
263 CompilerInstance &CI = getCompilerInstance();
264 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000265 if (!OS) return;
266
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000267 RewriteMacrosInInput(CI.getPreprocessor(), OS);
268}
269
270void RewriteTestAction::ExecuteAction() {
271 CompilerInstance &CI = getCompilerInstance();
272 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
Daniel Dunbar36043592009-12-03 09:13:30 +0000273 if (!OS) return;
274
Daniel Dunbar5f3b9972009-11-14 10:42:57 +0000275 DoRewriteTest(CI.getPreprocessor(), OS);
276}