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