1 //===--- FrontendAction.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/FrontendAction.h"
11 #include "clang/AST/ASTConsumer.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/AST/DeclGroup.h"
14 #include "clang/Lex/HeaderSearch.h"
15 #include "clang/Lex/Preprocessor.h"
16 #include "clang/Frontend/ASTUnit.h"
17 #include "clang/Frontend/CompilerInstance.h"
18 #include "clang/Frontend/FrontendDiagnostic.h"
19 #include "clang/Frontend/FrontendPluginRegistry.h"
20 #include "clang/Frontend/MultiplexConsumer.h"
21 #include "clang/Parse/ParseAST.h"
22 #include "clang/Serialization/ASTDeserializationListener.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Timer.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/raw_ostream.h"
27 using namespace clang
;
31 /// \brief Dumps deserialized declarations.
32 class DeserializedDeclsDumper
: public ASTDeserializationListener
{
33 ASTDeserializationListener
*Previous
;
36 DeserializedDeclsDumper(ASTDeserializationListener
*Previous
)
37 : Previous(Previous
) { }
39 virtual void DeclRead(serialization::DeclID ID
, const Decl
*D
) {
40 llvm::outs() << "PCH DECL: " << D
->getDeclKindName();
41 if (const NamedDecl
*ND
= dyn_cast
<NamedDecl
>(D
))
42 llvm::outs() << " - " << ND
->getNameAsString();
46 Previous
->DeclRead(ID
, D
);
50 /// \brief Checks deserialized declarations and emits error if a name
51 /// matches one given in command-line using -error-on-deserialized-decl.
52 class DeserializedDeclsChecker
: public ASTDeserializationListener
{
54 std::set
<std::string
> NamesToCheck
;
55 ASTDeserializationListener
*Previous
;
58 DeserializedDeclsChecker(ASTContext
&Ctx
,
59 const std::set
<std::string
> &NamesToCheck
,
60 ASTDeserializationListener
*Previous
)
61 : Ctx(Ctx
), NamesToCheck(NamesToCheck
), Previous(Previous
) { }
63 virtual void DeclRead(serialization::DeclID ID
, const Decl
*D
) {
64 if (const NamedDecl
*ND
= dyn_cast
<NamedDecl
>(D
))
65 if (NamesToCheck
.find(ND
->getNameAsString()) != NamesToCheck
.end()) {
67 = Ctx
.getDiagnostics().getCustomDiagID(Diagnostic::Error
,
68 "%0 was deserialized");
69 Ctx
.getDiagnostics().Report(Ctx
.getFullLoc(D
->getLocation()), DiagID
)
70 << ND
->getNameAsString();
74 Previous
->DeclRead(ID
, D
);
78 } // end anonymous namespace
80 FrontendAction::FrontendAction() : Instance(0) {}
82 FrontendAction::~FrontendAction() {}
84 void FrontendAction::setCurrentFile(llvm::StringRef Value
, InputKind Kind
,
87 CurrentFileKind
= Kind
;
88 CurrentASTUnit
.reset(AST
);
91 ASTConsumer
* FrontendAction::CreateWrappedASTConsumer(CompilerInstance
&CI
,
92 llvm::StringRef InFile
) {
93 ASTConsumer
* Consumer
= CreateASTConsumer(CI
, InFile
);
97 if (CI
.getFrontendOpts().AddPluginActions
.size() == 0)
100 // Make sure the non-plugin consumer is first, so that plugins can't
102 std::vector
<ASTConsumer
*> Consumers(1, Consumer
);
104 for (size_t i
= 0, e
= CI
.getFrontendOpts().AddPluginActions
.size();
106 // This is O(|plugins| * |add_plugins|), but since both numbers are
107 // way below 50 in practice, that's ok.
108 for (FrontendPluginRegistry::iterator
109 it
= FrontendPluginRegistry::begin(),
110 ie
= FrontendPluginRegistry::end();
112 if (it
->getName() == CI
.getFrontendOpts().AddPluginActions
[i
]) {
113 llvm::OwningPtr
<PluginASTAction
> P(it
->instantiate());
114 FrontendAction
* c
= P
.get();
115 if (P
->ParseArgs(CI
, CI
.getFrontendOpts().AddPluginArgs
[i
]))
116 Consumers
.push_back(c
->CreateASTConsumer(CI
, InFile
));
121 return new MultiplexConsumer(Consumers
);
124 bool FrontendAction::BeginSourceFile(CompilerInstance
&CI
,
125 llvm::StringRef Filename
,
126 InputKind InputKind
) {
127 assert(!Instance
&& "Already processing a source file!");
128 assert(!Filename
.empty() && "Unexpected empty filename!");
129 setCurrentFile(Filename
, InputKind
);
130 setCompilerInstance(&CI
);
132 // AST files follow a very different path, since they share objects via the
134 if (InputKind
== IK_AST
) {
135 assert(!usesPreprocessorOnly() &&
136 "Attempt to pass AST file to preprocessor only action!");
137 assert(hasASTFileSupport() &&
138 "This action does not have AST file support!");
140 llvm::IntrusiveRefCntPtr
<Diagnostic
> Diags(&CI
.getDiagnostics());
142 ASTUnit
*AST
= ASTUnit::LoadFromASTFile(Filename
, Diags
,
143 CI
.getFileSystemOpts());
147 setCurrentFile(Filename
, InputKind
, AST
);
149 // Set the shared objects, these are reset when we finish processing the
150 // file, otherwise the CompilerInstance will happily destroy them.
151 CI
.setFileManager(&AST
->getFileManager());
152 CI
.setSourceManager(&AST
->getSourceManager());
153 CI
.setPreprocessor(&AST
->getPreprocessor());
154 CI
.setASTContext(&AST
->getASTContext());
156 // Initialize the action.
157 if (!BeginSourceFileAction(CI
, Filename
))
160 /// Create the AST consumer.
161 CI
.setASTConsumer(CreateWrappedASTConsumer(CI
, Filename
));
162 if (!CI
.hasASTConsumer())
168 // Set up the file and source managers, if needed.
169 if (!CI
.hasFileManager())
170 CI
.createFileManager();
171 if (!CI
.hasSourceManager())
172 CI
.createSourceManager(CI
.getFileManager());
174 // IR files bypass the rest of initialization.
175 if (InputKind
== IK_LLVM_IR
) {
176 assert(hasIRSupport() &&
177 "This action does not have IR file support!");
179 // Inform the diagnostic client we are processing a source file.
180 CI
.getDiagnosticClient().BeginSourceFile(CI
.getLangOpts(), 0);
182 // Initialize the action.
183 if (!BeginSourceFileAction(CI
, Filename
))
189 // Set up the preprocessor.
190 CI
.createPreprocessor();
192 // Inform the diagnostic client we are processing a source file.
193 CI
.getDiagnosticClient().BeginSourceFile(CI
.getLangOpts(),
194 &CI
.getPreprocessor());
196 // Initialize the action.
197 if (!BeginSourceFileAction(CI
, Filename
))
200 /// Create the AST context and consumer unless this is a preprocessor only
202 if (!usesPreprocessorOnly()) {
203 CI
.createASTContext();
205 llvm::OwningPtr
<ASTConsumer
> Consumer(
206 CreateWrappedASTConsumer(CI
, Filename
));
210 CI
.getASTContext().setASTMutationListener(Consumer
->GetASTMutationListener());
213 if (!CI
.getPreprocessorOpts().ImplicitPCHInclude
.empty()) {
214 assert(hasPCHSupport() && "This action does not have PCH support!");
215 ASTDeserializationListener
*DeserialListener
216 = CI
.getInvocation().getFrontendOpts().ChainedPCH
?
217 Consumer
->GetASTDeserializationListener() : 0;
218 if (CI
.getPreprocessorOpts().DumpDeserializedPCHDecls
)
219 DeserialListener
= new DeserializedDeclsDumper(DeserialListener
);
220 if (!CI
.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn
.empty())
221 DeserialListener
= new DeserializedDeclsChecker(CI
.getASTContext(),
222 CI
.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn
,
224 CI
.createPCHExternalASTSource(
225 CI
.getPreprocessorOpts().ImplicitPCHInclude
,
226 CI
.getPreprocessorOpts().DisablePCHValidation
,
227 CI
.getPreprocessorOpts().DisableStatCache
,
229 if (!CI
.getASTContext().getExternalSource())
233 CI
.setASTConsumer(Consumer
.take());
234 if (!CI
.hasASTConsumer())
238 // Initialize builtin info as long as we aren't using an external AST
240 if (!CI
.hasASTContext() || !CI
.getASTContext().getExternalSource()) {
241 Preprocessor
&PP
= CI
.getPreprocessor();
242 PP
.getBuiltinInfo().InitializeBuiltins(PP
.getIdentifierTable(),
243 PP
.getLangOptions());
248 // If we failed, reset state since the client will not end up calling the
249 // matching EndSourceFile().
251 if (isCurrentFileAST()) {
253 CI
.takePreprocessor();
254 CI
.takeSourceManager();
255 CI
.takeFileManager();
258 CI
.getDiagnosticClient().EndSourceFile();
259 setCurrentFile("", IK_None
);
260 setCompilerInstance(0);
264 void FrontendAction::Execute() {
265 CompilerInstance
&CI
= getCompilerInstance();
267 // Initialize the main file entry. This needs to be delayed until after PCH
269 if (isCurrentFileAST()) {
270 // Set the main file ID to an empty file.
272 // FIXME: We probably shouldn't need this, but for now this is the
273 // simplest way to reuse the logic in ParseAST.
274 const char *EmptyStr
= "";
275 llvm::MemoryBuffer
*SB
=
276 llvm::MemoryBuffer::getMemBuffer(EmptyStr
, "<dummy input>");
277 CI
.getSourceManager().createMainFileIDForMemBuffer(SB
);
279 if (!CI
.InitializeSourceManager(getCurrentFile()))
283 if (CI
.hasFrontendTimer()) {
284 llvm::TimeRegion
Timer(CI
.getFrontendTimer());
287 else ExecuteAction();
290 void FrontendAction::EndSourceFile() {
291 CompilerInstance
&CI
= getCompilerInstance();
293 // Inform the diagnostic client we are done with this source file.
294 CI
.getDiagnosticClient().EndSourceFile();
296 // Finalize the action.
297 EndSourceFileAction();
299 // Release the consumer and the AST, in that order since the consumer may
300 // perform actions in its destructor which require the context.
302 // FIXME: There is more per-file stuff we could just drop here?
303 if (CI
.getFrontendOpts().DisableFree
) {
304 CI
.takeASTConsumer();
305 if (!isCurrentFileAST()) {
310 if (!isCurrentFileAST()) {
314 CI
.setASTConsumer(0);
317 // Inform the preprocessor we are done.
318 if (CI
.hasPreprocessor())
319 CI
.getPreprocessor().EndSourceFile();
321 if (CI
.getFrontendOpts().ShowStats
) {
322 llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
323 CI
.getPreprocessor().PrintStats();
324 CI
.getPreprocessor().getIdentifierTable().PrintStats();
325 CI
.getPreprocessor().getHeaderSearchInfo().PrintStats();
326 CI
.getSourceManager().PrintStats();
327 llvm::errs() << "\n";
330 // Cleanup the output streams, and erase the output files if we encountered
332 CI
.clearOutputFiles(/*EraseFiles=*/CI
.getDiagnostics().hasErrorOccurred());
334 if (isCurrentFileAST()) {
337 CI
.takePreprocessor();
338 CI
.takeSourceManager();
339 CI
.takeFileManager();
342 setCompilerInstance(0);
343 setCurrentFile("", IK_None
);
346 //===----------------------------------------------------------------------===//
348 //===----------------------------------------------------------------------===//
350 void ASTFrontendAction::ExecuteAction() {
351 CompilerInstance
&CI
= getCompilerInstance();
353 // FIXME: Move the truncation aspect of this into Sema, we delayed this till
354 // here so the source manager would be initialized.
355 if (hasCodeCompletionSupport() &&
356 !CI
.getFrontendOpts().CodeCompletionAt
.FileName
.empty())
357 CI
.createCodeCompletionConsumer();
359 // Use a code completion consumer?
360 CodeCompleteConsumer
*CompletionConsumer
= 0;
361 if (CI
.hasCodeCompletionConsumer())
362 CompletionConsumer
= &CI
.getCodeCompletionConsumer();
365 CI
.createSema(usesCompleteTranslationUnit(), CompletionConsumer
);
367 ParseAST(CI
.getSema(), CI
.getFrontendOpts().ShowStats
);
371 PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance
&CI
,
372 llvm::StringRef InFile
) {
373 llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");