FrontendAction.cpp revision 4182ed686283b72736b287cbe28583cb641f8934
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/LayoutOverrideSource.h" 22#include "clang/Frontend/MultiplexConsumer.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/raw_ostream.h" 30#include "llvm/Support/system_error.h" 31#include "llvm/Support/Timer.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.File.empty() && "Unexpected empty filename!"); 165 setCurrentInput(Input); 166 setCompilerInstance(&CI); 167 168 bool HasBegunSourceFile = false; 169 if (!BeginInvocation(CI)) 170 goto failure; 171 172 // AST files follow a very different path, since they share objects via the 173 // AST unit. 174 if (Input.Kind == IK_AST) { 175 assert(!usesPreprocessorOnly() && 176 "Attempt to pass AST file to preprocessor only action!"); 177 assert(hasASTFileSupport() && 178 "This action does not have AST file support!"); 179 180 IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); 181 std::string Error; 182 ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags, 183 CI.getFileSystemOpts()); 184 if (!AST) 185 goto failure; 186 187 setCurrentInput(Input, AST); 188 189 // Set the shared objects, these are reset when we finish processing the 190 // file, otherwise the CompilerInstance will happily destroy them. 191 CI.setFileManager(&AST->getFileManager()); 192 CI.setSourceManager(&AST->getSourceManager()); 193 CI.setPreprocessor(&AST->getPreprocessor()); 194 CI.setASTContext(&AST->getASTContext()); 195 196 // Initialize the action. 197 if (!BeginSourceFileAction(CI, Input.File)) 198 goto failure; 199 200 /// Create the AST consumer. 201 CI.setASTConsumer(CreateWrappedASTConsumer(CI, Input.File)); 202 if (!CI.hasASTConsumer()) 203 goto failure; 204 205 return true; 206 } 207 208 // Set up the file and source managers, if needed. 209 if (!CI.hasFileManager()) 210 CI.createFileManager(); 211 if (!CI.hasSourceManager()) 212 CI.createSourceManager(CI.getFileManager()); 213 214 // IR files bypass the rest of initialization. 215 if (Input.Kind == IK_LLVM_IR) { 216 assert(hasIRSupport() && 217 "This action does not have IR file support!"); 218 219 // Inform the diagnostic client we are processing a source file. 220 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); 221 HasBegunSourceFile = true; 222 223 // Initialize the action. 224 if (!BeginSourceFileAction(CI, Input.File)) 225 goto failure; 226 227 return true; 228 } 229 230 // If the implicit PCH include is actually a directory, rather than 231 // a single file, search for a suitable PCH file in that directory. 232 if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 233 FileManager &FileMgr = CI.getFileManager(); 234 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 235 StringRef PCHInclude = PPOpts.ImplicitPCHInclude; 236 if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { 237 llvm::error_code EC; 238 SmallString<128> DirNative; 239 llvm::sys::path::native(PCHDir->getName(), DirNative); 240 bool Found = false; 241 for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; 242 Dir != DirEnd && !EC; Dir.increment(EC)) { 243 // Check whether this is an acceptable AST file. 244 if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, 245 CI.getLangOpts(), 246 CI.getTargetOpts(), 247 CI.getPreprocessorOpts())) { 248 for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) { 249 if (PPOpts.Includes[I] == PPOpts.ImplicitPCHInclude) { 250 PPOpts.Includes[I] = Dir->path(); 251 PPOpts.ImplicitPCHInclude = Dir->path(); 252 Found = true; 253 break; 254 } 255 } 256 257 assert(Found && "Implicit PCH include not in includes list?"); 258 break; 259 } 260 } 261 262 if (!Found) { 263 CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; 264 return true; 265 } 266 } 267 } 268 269 // Set up the preprocessor. 270 CI.createPreprocessor(); 271 272 // Inform the diagnostic client we are processing a source file. 273 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 274 &CI.getPreprocessor()); 275 HasBegunSourceFile = true; 276 277 // Initialize the action. 278 if (!BeginSourceFileAction(CI, Input.File)) 279 goto failure; 280 281 /// Create the AST context and consumer unless this is a preprocessor only 282 /// action. 283 if (!usesPreprocessorOnly()) { 284 CI.createASTContext(); 285 286 OwningPtr<ASTConsumer> Consumer( 287 CreateWrappedASTConsumer(CI, Input.File)); 288 if (!Consumer) 289 goto failure; 290 291 CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); 292 CI.getPreprocessor().setPPMutationListener( 293 Consumer->GetPPMutationListener()); 294 295 if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { 296 // Convert headers to PCH and chain them. 297 OwningPtr<ExternalASTSource> source; 298 source.reset(ChainedIncludesSource::create(CI)); 299 if (!source) 300 goto failure; 301 CI.getASTContext().setExternalSource(source); 302 303 } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 304 // Use PCH. 305 assert(hasPCHSupport() && "This action does not have PCH support!"); 306 ASTDeserializationListener *DeserialListener = 307 Consumer->GetASTDeserializationListener(); 308 if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) 309 DeserialListener = new DeserializedDeclsDumper(DeserialListener); 310 if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) 311 DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), 312 CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, 313 DeserialListener); 314 CI.createPCHExternalASTSource( 315 CI.getPreprocessorOpts().ImplicitPCHInclude, 316 CI.getPreprocessorOpts().DisablePCHValidation, 317 CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, 318 DeserialListener); 319 if (!CI.getASTContext().getExternalSource()) 320 goto failure; 321 } 322 323 CI.setASTConsumer(Consumer.take()); 324 if (!CI.hasASTConsumer()) 325 goto failure; 326 } 327 328 // Initialize built-in info as long as we aren't using an external AST 329 // source. 330 if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { 331 Preprocessor &PP = CI.getPreprocessor(); 332 PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 333 PP.getLangOpts()); 334 } 335 336 // If there is a layout overrides file, attach an external AST source that 337 // provides the layouts from that file. 338 if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && 339 CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { 340 OwningPtr<ExternalASTSource> 341 Override(new LayoutOverrideSource( 342 CI.getFrontendOpts().OverrideRecordLayoutsFile)); 343 CI.getASTContext().setExternalSource(Override); 344 } 345 346 return true; 347 348 // If we failed, reset state since the client will not end up calling the 349 // matching EndSourceFile(). 350 failure: 351 if (isCurrentFileAST()) { 352 CI.setASTContext(0); 353 CI.setPreprocessor(0); 354 CI.setSourceManager(0); 355 CI.setFileManager(0); 356 } 357 358 if (HasBegunSourceFile) 359 CI.getDiagnosticClient().EndSourceFile(); 360 CI.clearOutputFiles(/*EraseFiles=*/true); 361 setCurrentInput(FrontendInputFile()); 362 setCompilerInstance(0); 363 return false; 364} 365 366bool FrontendAction::Execute() { 367 CompilerInstance &CI = getCompilerInstance(); 368 369 // Initialize the main file entry. This needs to be delayed until after PCH 370 // has loaded. 371 if (!isCurrentFileAST()) { 372 if (!CI.InitializeSourceManager(getCurrentFile(), 373 getCurrentInput().IsSystem 374 ? SrcMgr::C_System 375 : SrcMgr::C_User)) 376 return false; 377 } 378 379 if (CI.hasFrontendTimer()) { 380 llvm::TimeRegion Timer(CI.getFrontendTimer()); 381 ExecuteAction(); 382 } 383 else ExecuteAction(); 384 385 return true; 386} 387 388void FrontendAction::EndSourceFile() { 389 CompilerInstance &CI = getCompilerInstance(); 390 391 // Inform the diagnostic client we are done with this source file. 392 CI.getDiagnosticClient().EndSourceFile(); 393 394 // Finalize the action. 395 EndSourceFileAction(); 396 397 // Release the consumer and the AST, in that order since the consumer may 398 // perform actions in its destructor which require the context. 399 // 400 // FIXME: There is more per-file stuff we could just drop here? 401 if (CI.getFrontendOpts().DisableFree) { 402 CI.takeASTConsumer(); 403 if (!isCurrentFileAST()) { 404 CI.takeSema(); 405 CI.resetAndLeakASTContext(); 406 } 407 } else { 408 if (!isCurrentFileAST()) { 409 CI.setSema(0); 410 CI.setASTContext(0); 411 } 412 CI.setASTConsumer(0); 413 } 414 415 // Inform the preprocessor we are done. 416 if (CI.hasPreprocessor()) 417 CI.getPreprocessor().EndSourceFile(); 418 419 if (CI.getFrontendOpts().ShowStats) { 420 llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; 421 CI.getPreprocessor().PrintStats(); 422 CI.getPreprocessor().getIdentifierTable().PrintStats(); 423 CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); 424 CI.getSourceManager().PrintStats(); 425 llvm::errs() << "\n"; 426 } 427 428 // Cleanup the output streams, and erase the output files if we encountered 429 // an error. 430 CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred()); 431 432 if (isCurrentFileAST()) { 433 CI.takeSema(); 434 CI.resetAndLeakASTContext(); 435 CI.resetAndLeakPreprocessor(); 436 CI.resetAndLeakSourceManager(); 437 CI.resetAndLeakFileManager(); 438 } 439 440 setCompilerInstance(0); 441 setCurrentInput(FrontendInputFile()); 442} 443 444//===----------------------------------------------------------------------===// 445// Utility Actions 446//===----------------------------------------------------------------------===// 447 448void ASTFrontendAction::ExecuteAction() { 449 CompilerInstance &CI = getCompilerInstance(); 450 451 // FIXME: Move the truncation aspect of this into Sema, we delayed this till 452 // here so the source manager would be initialized. 453 if (hasCodeCompletionSupport() && 454 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 455 CI.createCodeCompletionConsumer(); 456 457 // Use a code completion consumer? 458 CodeCompleteConsumer *CompletionConsumer = 0; 459 if (CI.hasCodeCompletionConsumer()) 460 CompletionConsumer = &CI.getCodeCompletionConsumer(); 461 462 if (!CI.hasSema()) 463 CI.createSema(getTranslationUnitKind(), CompletionConsumer); 464 465 ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats, 466 CI.getFrontendOpts().SkipFunctionBodies); 467} 468 469void PluginASTAction::anchor() { } 470 471ASTConsumer * 472PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, 473 StringRef InFile) { 474 llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); 475} 476 477ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, 478 StringRef InFile) { 479 return WrappedAction->CreateASTConsumer(CI, InFile); 480} 481bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { 482 return WrappedAction->BeginInvocation(CI); 483} 484bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI, 485 StringRef Filename) { 486 WrappedAction->setCurrentInput(getCurrentInput()); 487 WrappedAction->setCompilerInstance(&CI); 488 return WrappedAction->BeginSourceFileAction(CI, Filename); 489} 490void WrapperFrontendAction::ExecuteAction() { 491 WrappedAction->ExecuteAction(); 492} 493void WrapperFrontendAction::EndSourceFileAction() { 494 WrappedAction->EndSourceFileAction(); 495} 496 497bool WrapperFrontendAction::usesPreprocessorOnly() const { 498 return WrappedAction->usesPreprocessorOnly(); 499} 500TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() { 501 return WrappedAction->getTranslationUnitKind(); 502} 503bool WrapperFrontendAction::hasPCHSupport() const { 504 return WrappedAction->hasPCHSupport(); 505} 506bool WrapperFrontendAction::hasASTFileSupport() const { 507 return WrappedAction->hasASTFileSupport(); 508} 509bool WrapperFrontendAction::hasIRSupport() const { 510 return WrappedAction->hasIRSupport(); 511} 512bool WrapperFrontendAction::hasCodeCompletionSupport() const { 513 return WrappedAction->hasCodeCompletionSupport(); 514} 515 516WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction) 517 : WrappedAction(WrappedAction) {} 518 519