//===--- ExecuteCompilerInvocation.cpp ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file holds ExecuteCompilerInvocation(). It is split into its own file to // minimize the impact of pulling in essentially everything else in Clang. // //===----------------------------------------------------------------------===// #include "clang/FrontendTool/Utils.h" #include "clang/ARCMigrate/ARCMTActions.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/Utils.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace llvm::opt; static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(CompilerInstance &CI) { using namespace clang::frontend; StringRef Action("unknown"); (void)Action; switch (CI.getFrontendOpts().ProgramAction) { case ASTDeclList: return llvm::make_unique<ASTDeclListAction>(); case ASTDump: return llvm::make_unique<ASTDumpAction>(); case ASTPrint: return llvm::make_unique<ASTPrintAction>(); case ASTView: return llvm::make_unique<ASTViewAction>(); case DumpRawTokens: return llvm::make_unique<DumpRawTokensAction>(); case DumpTokens: return llvm::make_unique<DumpTokensAction>(); case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>(); case EmitBC: return llvm::make_unique<EmitBCAction>(); case EmitHTML: return llvm::make_unique<HTMLPrintAction>(); case EmitLLVM: return llvm::make_unique<EmitLLVMAction>(); case EmitLLVMOnly: return llvm::make_unique<EmitLLVMOnlyAction>(); case EmitCodeGenOnly: return llvm::make_unique<EmitCodeGenOnlyAction>(); case EmitObj: return llvm::make_unique<EmitObjAction>(); case FixIt: return llvm::make_unique<FixItAction>(); case GenerateModule: return llvm::make_unique<GenerateModuleAction>(); case GeneratePCH: return llvm::make_unique<GeneratePCHAction>(); case GeneratePTH: return llvm::make_unique<GeneratePTHAction>(); case InitOnly: return llvm::make_unique<InitOnlyAction>(); case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>(); case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>(); case VerifyPCH: return llvm::make_unique<VerifyPCHAction>(); case PluginAction: { for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); it != ie; ++it) { if (it->getName() == CI.getFrontendOpts().ActionName) { std::unique_ptr<PluginASTAction> P(it->instantiate()); if ((P->getActionType() != PluginASTAction::ReplaceAction && P->getActionType() != PluginASTAction::Cmdline) || !P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs[it->getName()])) return nullptr; return std::move(P); } } CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << CI.getFrontendOpts().ActionName; return nullptr; } case PrintDeclContext: return llvm::make_unique<DeclContextPrintAction>(); case PrintPreamble: return llvm::make_unique<PrintPreambleAction>(); case PrintPreprocessedInput: { if (CI.getPreprocessorOutputOpts().RewriteIncludes) return llvm::make_unique<RewriteIncludesAction>(); return llvm::make_unique<PrintPreprocessedAction>(); } case RewriteMacros: return llvm::make_unique<RewriteMacrosAction>(); case RewriteTest: return llvm::make_unique<RewriteTestAction>(); #ifdef CLANG_ENABLE_OBJC_REWRITER case RewriteObjC: return llvm::make_unique<RewriteObjCAction>(); #else case RewriteObjC: Action = "RewriteObjC"; break; #endif #ifdef CLANG_ENABLE_ARCMT case MigrateSource: return llvm::make_unique<arcmt::MigrateSourceAction>(); #else case MigrateSource: Action = "MigrateSource"; break; #endif #ifdef CLANG_ENABLE_STATIC_ANALYZER case RunAnalysis: return llvm::make_unique<ento::AnalysisAction>(); #else case RunAnalysis: Action = "RunAnalysis"; break; #endif case RunPreprocessorOnly: return llvm::make_unique<PreprocessOnlyAction>(); } #if !defined(CLANG_ENABLE_ARCMT) || !defined(CLANG_ENABLE_STATIC_ANALYZER) \ || !defined(CLANG_ENABLE_OBJC_REWRITER) CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; return 0; #else llvm_unreachable("Invalid program action!"); #endif } static std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &CI) { // Create the underlying action. std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI); if (!Act) return nullptr; const FrontendOptions &FEOpts = CI.getFrontendOpts(); if (FEOpts.FixAndRecompile) { Act = llvm::make_unique<FixItRecompile>(std::move(Act)); } #ifdef CLANG_ENABLE_ARCMT if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource && CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) { // Potentially wrap the base FE action in an ARC Migrate Tool action. switch (FEOpts.ARCMTAction) { case FrontendOptions::ARCMT_None: break; case FrontendOptions::ARCMT_Check: Act = llvm::make_unique<arcmt::CheckAction>(std::move(Act)); break; case FrontendOptions::ARCMT_Modify: Act = llvm::make_unique<arcmt::ModifyAction>(std::move(Act)); break; case FrontendOptions::ARCMT_Migrate: Act = llvm::make_unique<arcmt::MigrateAction>(std::move(Act), FEOpts.MTMigrateDir, FEOpts.ARCMTMigrateReportOut, FEOpts.ARCMTMigrateEmitARCErrors); break; } if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) { Act = llvm::make_unique<arcmt::ObjCMigrateAction>(std::move(Act), FEOpts.MTMigrateDir, FEOpts.ObjCMTAction); } } #endif // If there are any AST files to merge, create a frontend action // adaptor to perform the merge. if (!FEOpts.ASTMergeFiles.empty()) Act = llvm::make_unique<ASTMergeAction>(std::move(Act), FEOpts.ASTMergeFiles); return Act; } bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { // Honor -help. if (Clang->getFrontendOpts().ShowHelp) { std::unique_ptr<OptTable> Opts(driver::createDriverOptTable()); Opts->PrintHelp(llvm::outs(), "clang -cc1", "LLVM 'Clang' Compiler: http://clang.llvm.org", /*Include=*/ driver::options::CC1Option, /*Exclude=*/ 0); return true; } // Honor -version. // // FIXME: Use a better -version message? if (Clang->getFrontendOpts().ShowVersion) { llvm::cl::PrintVersionMessage(); return true; } // Load any requested plugins. for (unsigned i = 0, e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) { const std::string &Path = Clang->getFrontendOpts().Plugins[i]; std::string Error; if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) << Path << Error; } // Check if any of the loaded plugins replaces the main AST action for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); it != ie; ++it) { std::unique_ptr<PluginASTAction> P(it->instantiate()); if (P->getActionType() == PluginASTAction::ReplaceAction) { Clang->getFrontendOpts().ProgramAction = clang::frontend::PluginAction; Clang->getFrontendOpts().ActionName = it->getName(); break; } } // Honor -mllvm. // // FIXME: Remove this, one day. // This should happen AFTER plugins have been loaded! if (!Clang->getFrontendOpts().LLVMArgs.empty()) { unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); auto Args = llvm::make_unique<const char*[]>(NumArgs + 2); Args[0] = "clang (LLVM option parsing)"; for (unsigned i = 0; i != NumArgs; ++i) Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); Args[NumArgs + 1] = nullptr; llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); } #ifdef CLANG_ENABLE_STATIC_ANALYZER // Honor -analyzer-checker-help. // This should happen AFTER plugins have been loaded! if (Clang->getAnalyzerOpts()->ShowCheckerHelp) { ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins); return true; } #endif // If there were errors in processing arguments, don't do anything else. if (Clang->getDiagnostics().hasErrorOccurred()) return false; // Create and execute the frontend action. std::unique_ptr<FrontendAction> Act(CreateFrontendAction(*Clang)); if (!Act) return false; bool Success = Clang->ExecuteAction(*Act); if (Clang->getFrontendOpts().DisableFree) BuryPointer(std::move(Act)); return Success; }