1 //===--- FrontendActions.cpp ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/Frontend/FrontendActions.h"
11 #include "clang/AST/ASTConsumer.h"
12 #include "clang/Lex/Pragma.h"
13 #include "clang/Lex/Preprocessor.h"
14 #include "clang/Parse/Parser.h"
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Frontend/ASTConsumers.h"
17 #include "clang/Frontend/ASTUnit.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Frontend/FrontendDiagnostic.h"
20 #include "clang/Frontend/Utils.h"
21 #include "clang/Serialization/ASTWriter.h"
22 #include "llvm/ADT/OwningPtr.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace clang
;
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
31 ASTConsumer
*InitOnlyAction::CreateASTConsumer(CompilerInstance
&CI
,
32 llvm::StringRef InFile
) {
33 return new ASTConsumer();
36 void InitOnlyAction::ExecuteAction() {
39 //===----------------------------------------------------------------------===//
40 // AST Consumer Actions
41 //===----------------------------------------------------------------------===//
43 ASTConsumer
*ASTPrintAction::CreateASTConsumer(CompilerInstance
&CI
,
44 llvm::StringRef InFile
) {
45 if (llvm::raw_ostream
*OS
= CI
.createDefaultOutputFile(false, InFile
))
46 return CreateASTPrinter(OS
);
50 ASTConsumer
*ASTPrintXMLAction::CreateASTConsumer(CompilerInstance
&CI
,
51 llvm::StringRef InFile
) {
52 if (llvm::raw_ostream
*OS
= CI
.createDefaultOutputFile(false, InFile
, "xml"))
53 return CreateASTPrinterXML(OS
);
57 ASTConsumer
*ASTDumpAction::CreateASTConsumer(CompilerInstance
&CI
,
58 llvm::StringRef InFile
) {
59 return CreateASTDumper();
62 ASTConsumer
*ASTDumpXMLAction::CreateASTConsumer(CompilerInstance
&CI
,
63 llvm::StringRef InFile
) {
64 llvm::raw_ostream
*OS
;
65 if (CI
.getFrontendOpts().OutputFile
.empty())
68 OS
= CI
.createDefaultOutputFile(false, InFile
);
70 return CreateASTDumperXML(*OS
);
73 ASTConsumer
*ASTViewAction::CreateASTConsumer(CompilerInstance
&CI
,
74 llvm::StringRef InFile
) {
75 return CreateASTViewer();
78 ASTConsumer
*DeclContextPrintAction::CreateASTConsumer(CompilerInstance
&CI
,
79 llvm::StringRef InFile
) {
80 return CreateDeclContextPrinter();
83 ASTConsumer
*GeneratePCHAction::CreateASTConsumer(CompilerInstance
&CI
,
84 llvm::StringRef InFile
) {
86 std::string OutputFile
;
87 llvm::raw_ostream
*OS
= 0;
89 if (ComputeASTConsumerArguments(CI
, InFile
, Sysroot
, OutputFile
, OS
, Chaining
))
92 const char *isysroot
= CI
.getFrontendOpts().RelocatablePCH
?
94 return new PCHGenerator(CI
.getPreprocessor(), OutputFile
, Chaining
, isysroot
, OS
);
97 bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance
&CI
,
98 llvm::StringRef InFile
,
100 std::string
&OutputFile
,
101 llvm::raw_ostream
*&OS
,
103 Sysroot
= CI
.getHeaderSearchOpts().Sysroot
;
104 if (CI
.getFrontendOpts().RelocatablePCH
&& Sysroot
.empty()) {
105 CI
.getDiagnostics().Report(diag::err_relocatable_without_isysroot
);
109 // We use createOutputFile here because this is exposed via libclang, and we
110 // must disable the RemoveFileOnSignal behavior.
111 OS
= CI
.createOutputFile(CI
.getFrontendOpts().OutputFile
, /*Binary=*/true,
112 /*RemoveFileOnSignal=*/false, InFile
);
116 OutputFile
= CI
.getFrontendOpts().OutputFile
;
117 Chaining
= CI
.getInvocation().getFrontendOpts().ChainedPCH
&&
118 !CI
.getPreprocessorOpts().ImplicitPCHInclude
.empty();
122 ASTConsumer
*InheritanceViewAction::CreateASTConsumer(CompilerInstance
&CI
,
123 llvm::StringRef InFile
) {
124 return CreateInheritanceViewer(CI
.getFrontendOpts().ViewClassInheritance
);
127 ASTConsumer
*SyntaxOnlyAction::CreateASTConsumer(CompilerInstance
&CI
,
128 llvm::StringRef InFile
) {
129 return new ASTConsumer();
132 //===----------------------------------------------------------------------===//
133 // Preprocessor Actions
134 //===----------------------------------------------------------------------===//
136 void DumpRawTokensAction::ExecuteAction() {
137 Preprocessor
&PP
= getCompilerInstance().getPreprocessor();
138 SourceManager
&SM
= PP
.getSourceManager();
140 // Start lexing the specified input file.
141 const llvm::MemoryBuffer
*FromFile
= SM
.getBuffer(SM
.getMainFileID());
142 Lexer
RawLex(SM
.getMainFileID(), FromFile
, SM
, PP
.getLangOptions());
143 RawLex
.SetKeepWhitespaceMode(true);
146 RawLex
.LexFromRawLexer(RawTok
);
147 while (RawTok
.isNot(tok::eof
)) {
148 PP
.DumpToken(RawTok
, true);
149 llvm::errs() << "\n";
150 RawLex
.LexFromRawLexer(RawTok
);
154 void DumpTokensAction::ExecuteAction() {
155 Preprocessor
&PP
= getCompilerInstance().getPreprocessor();
156 // Start preprocessing the specified input file.
158 PP
.EnterMainSourceFile();
161 PP
.DumpToken(Tok
, true);
162 llvm::errs() << "\n";
163 } while (Tok
.isNot(tok::eof
));
166 void GeneratePTHAction::ExecuteAction() {
167 CompilerInstance
&CI
= getCompilerInstance();
168 if (CI
.getFrontendOpts().OutputFile
.empty() ||
169 CI
.getFrontendOpts().OutputFile
== "-") {
170 // FIXME: Don't fail this way.
171 // FIXME: Verify that we can actually seek in the given file.
172 llvm::report_fatal_error("PTH requires a seekable file for output!");
174 llvm::raw_fd_ostream
*OS
=
175 CI
.createDefaultOutputFile(true, getCurrentFile());
178 CacheTokens(CI
.getPreprocessor(), OS
);
181 void PreprocessOnlyAction::ExecuteAction() {
182 Preprocessor
&PP
= getCompilerInstance().getPreprocessor();
184 // Ignore unknown pragmas.
185 PP
.AddPragmaHandler(new EmptyPragmaHandler());
188 // Start parsing the specified input file.
189 PP
.EnterMainSourceFile();
192 } while (Tok
.isNot(tok::eof
));
195 void PrintPreprocessedAction::ExecuteAction() {
196 CompilerInstance
&CI
= getCompilerInstance();
197 // Output file needs to be set to 'Binary', to avoid converting Unix style
198 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
199 llvm::raw_ostream
*OS
= CI
.createDefaultOutputFile(true, getCurrentFile());
202 DoPrintPreprocessedInput(CI
.getPreprocessor(), OS
,
203 CI
.getPreprocessorOutputOpts());
206 void PrintPreambleAction::ExecuteAction() {
207 switch (getCurrentFileKind()) {
218 case IK_PreprocessedC
:
219 case IK_PreprocessedCXX
:
220 case IK_PreprocessedObjC
:
221 case IK_PreprocessedObjCXX
:
224 // We can't do anything with these.
228 CompilerInstance
&CI
= getCompilerInstance();
229 llvm::MemoryBuffer
*Buffer
230 = CI
.getFileManager().getBufferForFile(getCurrentFile());
232 unsigned Preamble
= Lexer::ComputePreamble(Buffer
).first
;
233 llvm::outs().write(Buffer
->getBufferStart(), Preamble
);