1 //===--- FrontendAction.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/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/ChainedIncludesSource.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Frontend/FrontendDiagnostic.h"
20 #include "clang/Frontend/FrontendPluginRegistry.h"
21 #include "clang/Frontend/MultiplexConsumer.h"
22 #include "clang/Parse/ParseAST.h"
23 #include "clang/Serialization/ASTDeserializationListener.h"
24 #include "clang/Serialization/ASTReader.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/Timer.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/raw_ostream.h"
29 using namespace clang;
30 
31 namespace {
32 
33 class DelegatingDeserializationListener : public ASTDeserializationListener {
34   ASTDeserializationListener *Previous;
35 
36 public:
37   explicit DelegatingDeserializationListener(
38                                            ASTDeserializationListener *Previous)
39     : Previous(Previous) { }
40 
41   virtual void ReaderInitialized(ASTReader *Reader) {
42     if (Previous)
43       Previous->ReaderInitialized(Reader);
44   }
45   virtual void IdentifierRead(serialization::IdentID ID,
46                               IdentifierInfo *II) {
47     if (Previous)
48       Previous->IdentifierRead(ID, II);
49   }
50   virtual void TypeRead(serialization::TypeIdx Idx, QualType T) {
51     if (Previous)
52       Previous->TypeRead(Idx, T);
53   }
54   virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
55     if (Previous)
56       Previous->DeclRead(ID, D);
57   }
58   virtual void SelectorRead(serialization::SelectorID ID, Selector Sel) {
59     if (Previous)
60       Previous->SelectorRead(ID, Sel);
61   }
62   virtual void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,
63                                    MacroDefinition *MD) {
64     if (Previous)
65       Previous->MacroDefinitionRead(PPID, MD);
66   }
67 };
68 
69 /// \brief Dumps deserialized declarations.
70 class DeserializedDeclsDumper : public DelegatingDeserializationListener {
71 public:
72   explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous)
73     : DelegatingDeserializationListener(Previous) { }
74 
75   virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
76     llvm::outs() << "PCH DECL: " << D->getDeclKindName();
77     if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
78       llvm::outs() << " - " << ND->getNameAsString();
79     llvm::outs() << "\n";
80 
81     DelegatingDeserializationListener::DeclRead(ID, D);
82   }
83 };
84 
85   /// \brief Checks deserialized declarations and emits error if a name
86   /// matches one given in command-line using -error-on-deserialized-decl.
87   class DeserializedDeclsChecker : public DelegatingDeserializationListener {
88     ASTContext &Ctx;
89     std::set<std::string> NamesToCheck;
90 
91   public:
92     DeserializedDeclsChecker(ASTContext &Ctx,
93                              const std::set<std::string> &NamesToCheck,
94                              ASTDeserializationListener *Previous)
95       : DelegatingDeserializationListener(Previous),
96         Ctx(Ctx), NamesToCheck(NamesToCheck) { }
97 
98     virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
99       if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
100         if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
101           unsigned DiagID
102             = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
103                                                    "%0 was deserialized");
104           Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
105               << ND->getNameAsString();
106         }
107 
108       DelegatingDeserializationListener::DeclRead(ID, D);
109     }
110 };
111 
112 } // end anonymous namespace
113 
114 FrontendAction::FrontendAction() : Instance(0) {}
115 
116 FrontendAction::~FrontendAction() {}
117 
118 void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
119                                      ASTUnit *AST) {
120   this->CurrentInput = CurrentInput;
121   CurrentASTUnit.reset(AST);
122 }
123 
124 ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
125                                                       StringRef InFile) {
126   ASTConsumer* Consumer = CreateASTConsumer(CI, InFile);
127   if (!Consumer)
128     return 0;
129 
130   if (CI.getFrontendOpts().AddPluginActions.size() == 0)
131     return Consumer;
132 
133   // Make sure the non-plugin consumer is first, so that plugins can't
134   // modifiy the AST.
135   std::vector<ASTConsumer*> Consumers(1, Consumer);
136 
137   for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size();
138        i != e; ++i) {
139     // This is O(|plugins| * |add_plugins|), but since both numbers are
140     // way below 50 in practice, that's ok.
141     for (FrontendPluginRegistry::iterator
142         it = FrontendPluginRegistry::begin(),
143         ie = FrontendPluginRegistry::end();
144         it != ie; ++it) {
145       if (it->getName() == CI.getFrontendOpts().AddPluginActions[i]) {
146         llvm::OwningPtr<PluginASTAction> P(it->instantiate());
147         FrontendAction* c = P.get();
148         if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i]))
149           Consumers.push_back(c->CreateASTConsumer(CI, InFile));
150       }
151     }
152   }
153 
154   return new MultiplexConsumer(Consumers);
155 }
156 
157 bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
158                                      const FrontendInputFile &Input) {
159   assert(!Instance && "Already processing a source file!");
160   assert(!Input.File.empty() && "Unexpected empty filename!");
161   setCurrentInput(Input);
162   setCompilerInstance(&CI);
163 
164   if (!BeginInvocation(CI))
165     goto failure;
166 
167   // AST files follow a very different path, since they share objects via the
168   // AST unit.
169   if (Input.Kind == IK_AST) {
170     assert(!usesPreprocessorOnly() &&
171            "Attempt to pass AST file to preprocessor only action!");
172     assert(hasASTFileSupport() &&
173            "This action does not have AST file support!");
174 
175     llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
176     std::string Error;
177     ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags,
178                                             CI.getFileSystemOpts());
179     if (!AST)
180       goto failure;
181 
182     setCurrentInput(Input, AST);
183 
184     // Set the shared objects, these are reset when we finish processing the
185     // file, otherwise the CompilerInstance will happily destroy them.
186     CI.setFileManager(&AST->getFileManager());
187     CI.setSourceManager(&AST->getSourceManager());
188     CI.setPreprocessor(&AST->getPreprocessor());
189     CI.setASTContext(&AST->getASTContext());
190 
191     // Initialize the action.
192     if (!BeginSourceFileAction(CI, Input.File))
193       goto failure;
194 
195     /// Create the AST consumer.
196     CI.setASTConsumer(CreateWrappedASTConsumer(CI, Input.File));
197     if (!CI.hasASTConsumer())
198       goto failure;
199 
200     return true;
201   }
202 
203   // Set up the file and source managers, if needed.
204   if (!CI.hasFileManager())
205     CI.createFileManager();
206   if (!CI.hasSourceManager())
207     CI.createSourceManager(CI.getFileManager());
208 
209   // IR files bypass the rest of initialization.
210   if (Input.Kind == IK_LLVM_IR) {
211     assert(hasIRSupport() &&
212            "This action does not have IR file support!");
213 
214     // Inform the diagnostic client we are processing a source file.
215     CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
216 
217     // Initialize the action.
218     if (!BeginSourceFileAction(CI, Input.File))
219       goto failure;
220 
221     return true;
222   }
223 
224   // Set up the preprocessor.
225   CI.createPreprocessor();
226 
227   // Inform the diagnostic client we are processing a source file.
228   CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
229                                            &CI.getPreprocessor());
230 
231   // Initialize the action.
232   if (!BeginSourceFileAction(CI, Input.File))
233     goto failure;
234 
235   /// Create the AST context and consumer unless this is a preprocessor only
236   /// action.
237   if (!usesPreprocessorOnly()) {
238     CI.createASTContext();
239 
240     llvm::OwningPtr<ASTConsumer> Consumer(
241                                    CreateWrappedASTConsumer(CI, Input.File));
242     if (!Consumer)
243       goto failure;
244 
245     CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
246 
247     if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
248       // Convert headers to PCH and chain them.
249       llvm::OwningPtr<ExternalASTSource> source;
250       source.reset(ChainedIncludesSource::create(CI));
251       if (!source)
252         goto failure;
253       CI.getASTContext().setExternalSource(source);
254 
255     } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
256       // Use PCH.
257       assert(hasPCHSupport() && "This action does not have PCH support!");
258       ASTDeserializationListener *DeserialListener =
259           Consumer->GetASTDeserializationListener();
260       if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls)
261         DeserialListener = new DeserializedDeclsDumper(DeserialListener);
262       if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty())
263         DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(),
264                          CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
265                                                         DeserialListener);
266       CI.createPCHExternalASTSource(
267                                 CI.getPreprocessorOpts().ImplicitPCHInclude,
268                                 CI.getPreprocessorOpts().DisablePCHValidation,
269                                 CI.getPreprocessorOpts().DisableStatCache,
270                                 DeserialListener);
271       if (!CI.getASTContext().getExternalSource())
272         goto failure;
273     }
274 
275     CI.setASTConsumer(Consumer.take());
276     if (!CI.hasASTConsumer())
277       goto failure;
278   }
279 
280   // Initialize built-in info as long as we aren't using an external AST
281   // source.
282   if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
283     Preprocessor &PP = CI.getPreprocessor();
284     PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
285                                            PP.getLangOptions());
286   }
287 
288   return true;
289 
290   // If we failed, reset state since the client will not end up calling the
291   // matching EndSourceFile().
292   failure:
293   if (isCurrentFileAST()) {
294     CI.setASTContext(0);
295     CI.setPreprocessor(0);
296     CI.setSourceManager(0);
297     CI.setFileManager(0);
298   }
299 
300   CI.getDiagnosticClient().EndSourceFile();
301   setCurrentInput(FrontendInputFile());
302   setCompilerInstance(0);
303   return false;
304 }
305 
306 void FrontendAction::Execute() {
307   CompilerInstance &CI = getCompilerInstance();
308 
309   // Initialize the main file entry. This needs to be delayed until after PCH
310   // has loaded.
311   if (!isCurrentFileAST()) {
312     if (!CI.InitializeSourceManager(getCurrentFile()))
313       return;
314   }
315 
316   if (CI.hasFrontendTimer()) {
317     llvm::TimeRegion Timer(CI.getFrontendTimer());
318     ExecuteAction();
319   }
320   else ExecuteAction();
321 }
322 
323 void FrontendAction::EndSourceFile() {
324   CompilerInstance &CI = getCompilerInstance();
325 
326   // Inform the diagnostic client we are done with this source file.
327   CI.getDiagnosticClient().EndSourceFile();
328 
329   // Finalize the action.
330   EndSourceFileAction();
331 
332   // Release the consumer and the AST, in that order since the consumer may
333   // perform actions in its destructor which require the context.
334   //
335   // FIXME: There is more per-file stuff we could just drop here?
336   if (CI.getFrontendOpts().DisableFree) {
337     CI.takeASTConsumer();
338     if (!isCurrentFileAST()) {
339       CI.takeSema();
340       CI.resetAndLeakASTContext();
341     }
342   } else {
343     if (!isCurrentFileAST()) {
344       CI.setSema(0);
345       CI.setASTContext(0);
346     }
347     CI.setASTConsumer(0);
348   }
349 
350   // Inform the preprocessor we are done.
351   if (CI.hasPreprocessor())
352     CI.getPreprocessor().EndSourceFile();
353 
354   if (CI.getFrontendOpts().ShowStats) {
355     llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
356     CI.getPreprocessor().PrintStats();
357     CI.getPreprocessor().getIdentifierTable().PrintStats();
358     CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
359     CI.getSourceManager().PrintStats();
360     llvm::errs() << "\n";
361   }
362 
363   // Cleanup the output streams, and erase the output files if we encountered
364   // an error.
365   CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred());
366 
367   if (isCurrentFileAST()) {
368     CI.takeSema();
369     CI.resetAndLeakASTContext();
370     CI.resetAndLeakPreprocessor();
371     CI.resetAndLeakSourceManager();
372     CI.resetAndLeakFileManager();
373   }
374 
375   setCompilerInstance(0);
376   setCurrentInput(FrontendInputFile());
377 }
378 
379 //===----------------------------------------------------------------------===//
380 // Utility Actions
381 //===----------------------------------------------------------------------===//
382 
383 void ASTFrontendAction::ExecuteAction() {
384   CompilerInstance &CI = getCompilerInstance();
385 
386   // FIXME: Move the truncation aspect of this into Sema, we delayed this till
387   // here so the source manager would be initialized.
388   if (hasCodeCompletionSupport() &&
389       !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
390     CI.createCodeCompletionConsumer();
391 
392   // Use a code completion consumer?
393   CodeCompleteConsumer *CompletionConsumer = 0;
394   if (CI.hasCodeCompletionConsumer())
395     CompletionConsumer = &CI.getCodeCompletionConsumer();
396 
397   if (!CI.hasSema())
398     CI.createSema(getTranslationUnitKind(), CompletionConsumer);
399 
400   ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
401 }
402 
403 void PluginASTAction::anchor() { }
404 
405 ASTConsumer *
406 PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
407                                               StringRef InFile) {
408   llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
409 }
410 
411 ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
412                                                       StringRef InFile) {
413   return WrappedAction->CreateASTConsumer(CI, InFile);
414 }
415 bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
416   return WrappedAction->BeginInvocation(CI);
417 }
418 bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI,
419                                                   StringRef Filename) {
420   WrappedAction->setCurrentInput(getCurrentInput());
421   WrappedAction->setCompilerInstance(&CI);
422   return WrappedAction->BeginSourceFileAction(CI, Filename);
423 }
424 void WrapperFrontendAction::ExecuteAction() {
425   WrappedAction->ExecuteAction();
426 }
427 void WrapperFrontendAction::EndSourceFileAction() {
428   WrappedAction->EndSourceFileAction();
429 }
430 
431 bool WrapperFrontendAction::usesPreprocessorOnly() const {
432   return WrappedAction->usesPreprocessorOnly();
433 }
434 TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {
435   return WrappedAction->getTranslationUnitKind();
436 }
437 bool WrapperFrontendAction::hasPCHSupport() const {
438   return WrappedAction->hasPCHSupport();
439 }
440 bool WrapperFrontendAction::hasASTFileSupport() const {
441   return WrappedAction->hasASTFileSupport();
442 }
443 bool WrapperFrontendAction::hasIRSupport() const {
444   return WrappedAction->hasIRSupport();
445 }
446 bool WrapperFrontendAction::hasCodeCompletionSupport() const {
447   return WrappedAction->hasCodeCompletionSupport();
448 }
449 
450 WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction)
451   : WrappedAction(WrappedAction) {}
452 
453