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