CompilerInstance.cpp revision 210299
1293010Sadrian//===--- CompilerInstance.cpp ---------------------------------------------===// 2293010Sadrian// 3293010Sadrian// The LLVM Compiler Infrastructure 4293010Sadrian// 5293010Sadrian// This file is distributed under the University of Illinois Open Source 6293010Sadrian// License. See LICENSE.TXT for details. 7293010Sadrian// 8293010Sadrian//===----------------------------------------------------------------------===// 9293010Sadrian 10293010Sadrian#include "clang/Frontend/CompilerInstance.h" 11293010Sadrian#include "clang/AST/ASTConsumer.h" 12293010Sadrian#include "clang/AST/ASTContext.h" 13293010Sadrian#include "clang/Basic/Diagnostic.h" 14293010Sadrian#include "clang/Basic/FileManager.h" 15293010Sadrian#include "clang/Basic/SourceManager.h" 16293010Sadrian#include "clang/Basic/TargetInfo.h" 17293010Sadrian#include "clang/Basic/Version.h" 18293010Sadrian#include "clang/Lex/HeaderSearch.h" 19293010Sadrian#include "clang/Lex/Preprocessor.h" 20293010Sadrian#include "clang/Lex/PTHManager.h" 21293010Sadrian#include "clang/Frontend/ChainedDiagnosticClient.h" 22293010Sadrian#include "clang/Frontend/FrontendAction.h" 23293010Sadrian#include "clang/Frontend/PCHReader.h" 24293010Sadrian#include "clang/Frontend/FrontendDiagnostic.h" 25293010Sadrian#include "clang/Frontend/TextDiagnosticPrinter.h" 26293010Sadrian#include "clang/Frontend/VerifyDiagnosticsClient.h" 27293010Sadrian#include "clang/Frontend/Utils.h" 28293010Sadrian#include "clang/Sema/CodeCompleteConsumer.h" 29293010Sadrian#include "llvm/LLVMContext.h" 30293010Sadrian#include "llvm/Support/MemoryBuffer.h" 31293010Sadrian#include "llvm/Support/raw_ostream.h" 32293010Sadrian#include "llvm/ADT/Statistic.h" 33293010Sadrian#include "llvm/Support/Timer.h" 34293010Sadrian#include "llvm/System/Host.h" 35293010Sadrian#include "llvm/System/Path.h" 36293010Sadrian#include "llvm/System/Program.h" 37293010Sadrianusing namespace clang; 38293010Sadrian 39293010SadrianCompilerInstance::CompilerInstance() 40293010Sadrian : Invocation(new CompilerInvocation()), Reader(0) { 41293010Sadrian} 42293010Sadrian 43293010SadrianCompilerInstance::~CompilerInstance() { 44293010Sadrian} 45293010Sadrian 46293010Sadrianvoid CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) { 47293010Sadrian LLVMContext.reset(Value); 48293010Sadrian} 49293010Sadrian 50293010Sadrianvoid CompilerInstance::setInvocation(CompilerInvocation *Value) { 51293010Sadrian Invocation.reset(Value); 52293010Sadrian} 53293010Sadrian 54293010Sadrianvoid CompilerInstance::setDiagnostics(Diagnostic *Value) { 55293010Sadrian Diagnostics = Value; 56293010Sadrian} 57293010Sadrian 58293010Sadrianvoid CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { 59293010Sadrian DiagClient.reset(Value); 60293010Sadrian} 61293010Sadrian 62293010Sadrianvoid CompilerInstance::setTarget(TargetInfo *Value) { 63293010Sadrian Target.reset(Value); 64293010Sadrian} 65293010Sadrian 66293010Sadrianvoid CompilerInstance::setFileManager(FileManager *Value) { 67293010Sadrian FileMgr.reset(Value); 68293010Sadrian} 69293010Sadrian 70293010Sadrianvoid CompilerInstance::setSourceManager(SourceManager *Value) { 71293010Sadrian SourceMgr.reset(Value); 72293010Sadrian} 73293010Sadrian 74293010Sadrianvoid CompilerInstance::setPreprocessor(Preprocessor *Value) { 75293010Sadrian PP.reset(Value); 76293010Sadrian} 77293010Sadrian 78293010Sadrianvoid CompilerInstance::setASTContext(ASTContext *Value) { 79293010Sadrian Context.reset(Value); 80293010Sadrian} 81293010Sadrian 82293010Sadrianvoid CompilerInstance::setASTConsumer(ASTConsumer *Value) { 83293010Sadrian Consumer.reset(Value); 84293010Sadrian} 85293010Sadrian 86293010Sadrianvoid CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 87293010Sadrian CompletionConsumer.reset(Value); 88293010Sadrian} 89293010Sadrian 90293010Sadrian// Diagnostics 91293010Sadriannamespace { 92293010Sadrian class BinaryDiagnosticSerializer : public DiagnosticClient { 93293010Sadrian llvm::raw_ostream &OS; 94293010Sadrian SourceManager *SourceMgr; 95293010Sadrian public: 96293010Sadrian explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS) 97293010Sadrian : OS(OS), SourceMgr(0) { } 98293010Sadrian 99293010Sadrian virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, 100293010Sadrian const DiagnosticInfo &Info); 101293010Sadrian }; 102293010Sadrian} 103293010Sadrian 104293010Sadrianvoid BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel, 105293010Sadrian const DiagnosticInfo &Info) { 106293010Sadrian StoredDiagnostic(DiagLevel, Info).Serialize(OS); 107293010Sadrian} 108293010Sadrian 109293010Sadrianstatic void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 110293010Sadrian unsigned argc, char **argv, 111293010Sadrian Diagnostic &Diags) { 112293010Sadrian std::string ErrorInfo; 113293010Sadrian llvm::OwningPtr<llvm::raw_ostream> OS( 114293010Sadrian new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo)); 115293010Sadrian if (!ErrorInfo.empty()) { 116293010Sadrian Diags.Report(diag::err_fe_unable_to_open_logfile) 117293010Sadrian << DiagOpts.DumpBuildInformation << ErrorInfo; 118293010Sadrian return; 119293010Sadrian } 120293010Sadrian 121293010Sadrian (*OS) << "clang -cc1 command line arguments: "; 122293010Sadrian for (unsigned i = 0; i != argc; ++i) 123293010Sadrian (*OS) << argv[i] << ' '; 124293010Sadrian (*OS) << '\n'; 125293010Sadrian 126293010Sadrian // Chain in a diagnostic client which will log the diagnostics. 127293010Sadrian DiagnosticClient *Logger = 128293010Sadrian new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true); 129293010Sadrian Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger)); 130293010Sadrian} 131293010Sadrian 132293010Sadrianvoid CompilerInstance::createDiagnostics(int Argc, char **Argv) { 133293010Sadrian Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv); 134293010Sadrian 135293010Sadrian if (Diagnostics) 136293010Sadrian DiagClient.reset(Diagnostics->getClient()); 137293010Sadrian} 138293010Sadrian 139293010Sadrianllvm::IntrusiveRefCntPtr<Diagnostic> 140293010SadrianCompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 141293010Sadrian int Argc, char **Argv) { 142293010Sadrian llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic()); 143293010Sadrian 144293010Sadrian // Create the diagnostic client for reporting errors or for 145293010Sadrian // implementing -verify. 146293010Sadrian llvm::OwningPtr<DiagnosticClient> DiagClient; 147293010Sadrian if (Opts.BinaryOutput) { 148293010Sadrian if (llvm::sys::Program::ChangeStderrToBinary()) { 149293010Sadrian // We weren't able to set standard error to binary, which is a 150293010Sadrian // bit of a problem. So, just create a text diagnostic printer 151293010Sadrian // to complain about this problem, and pretend that the user 152293010Sadrian // didn't try to use binary output. 153293010Sadrian DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 154293010Sadrian Diags->setClient(DiagClient.take()); 155293010Sadrian Diags->Report(diag::err_fe_stderr_binary); 156293010Sadrian return Diags; 157293010Sadrian } else { 158293010Sadrian DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs())); 159293010Sadrian } 160293010Sadrian } else { 161293010Sadrian DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 162293010Sadrian } 163293010Sadrian 164293010Sadrian // Chain in -verify checker, if requested. 165293010Sadrian if (Opts.VerifyDiagnostics) 166293010Sadrian DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take())); 167293010Sadrian 168293010Sadrian Diags->setClient(DiagClient.take()); 169293010Sadrian if (!Opts.DumpBuildInformation.empty()) 170293010Sadrian SetUpBuildDumpLog(Opts, Argc, Argv, *Diags); 171293010Sadrian 172293010Sadrian // Configure our handling of diagnostics. 173293010Sadrian ProcessWarningOptions(*Diags, Opts); 174293010Sadrian 175293010Sadrian return Diags; 176293010Sadrian} 177293010Sadrian 178293010Sadrian// File Manager 179293010Sadrian 180293010Sadrianvoid CompilerInstance::createFileManager() { 181293010Sadrian FileMgr.reset(new FileManager()); 182293010Sadrian} 183293010Sadrian 184293010Sadrian// Source Manager 185293010Sadrian 186293010Sadrianvoid CompilerInstance::createSourceManager() { 187293010Sadrian SourceMgr.reset(new SourceManager(getDiagnostics())); 188293010Sadrian} 189293010Sadrian 190293010Sadrian// Preprocessor 191293010Sadrian 192293010Sadrianvoid CompilerInstance::createPreprocessor() { 193293010Sadrian PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 194293010Sadrian getPreprocessorOpts(), getHeaderSearchOpts(), 195293010Sadrian getDependencyOutputOpts(), getTarget(), 196293010Sadrian getFrontendOpts(), getSourceManager(), 197293010Sadrian getFileManager())); 198293010Sadrian} 199293010Sadrian 200293010SadrianPreprocessor * 201293010SadrianCompilerInstance::createPreprocessor(Diagnostic &Diags, 202293010Sadrian const LangOptions &LangInfo, 203293010Sadrian const PreprocessorOptions &PPOpts, 204293010Sadrian const HeaderSearchOptions &HSOpts, 205293010Sadrian const DependencyOutputOptions &DepOpts, 206293010Sadrian const TargetInfo &Target, 207293010Sadrian const FrontendOptions &FEOpts, 208293010Sadrian SourceManager &SourceMgr, 209293010Sadrian FileManager &FileMgr) { 210293010Sadrian // Create a PTH manager if we are using some form of a token cache. 211293010Sadrian PTHManager *PTHMgr = 0; 212293010Sadrian if (!PPOpts.TokenCache.empty()) 213293010Sadrian PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags); 214293010Sadrian 215293010Sadrian // Create the Preprocessor. 216293010Sadrian HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 217293010Sadrian Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 218293010Sadrian SourceMgr, *HeaderInfo, PTHMgr, 219293010Sadrian /*OwnsHeaderSearch=*/true); 220293010Sadrian 221293010Sadrian // Note that this is different then passing PTHMgr to Preprocessor's ctor. 222293010Sadrian // That argument is used as the IdentifierInfoLookup argument to 223293010Sadrian // IdentifierTable's ctor. 224293010Sadrian if (PTHMgr) { 225293010Sadrian PTHMgr->setPreprocessor(PP); 226293010Sadrian PP->setPTHManager(PTHMgr); 227293010Sadrian } 228293010Sadrian 229293010Sadrian if (PPOpts.DetailedRecord) 230293010Sadrian PP->createPreprocessingRecord(); 231293010Sadrian 232293010Sadrian InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts); 233293010Sadrian 234293010Sadrian // Handle generating dependencies, if requested. 235293010Sadrian if (!DepOpts.OutputFile.empty()) 236293010Sadrian AttachDependencyFileGen(*PP, DepOpts); 237293010Sadrian 238293010Sadrian return PP; 239293010Sadrian} 240293010Sadrian 241293010Sadrian// ASTContext 242293010Sadrian 243293010Sadrianvoid CompilerInstance::createASTContext() { 244293010Sadrian Preprocessor &PP = getPreprocessor(); 245293010Sadrian Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), 246293010Sadrian getTarget(), PP.getIdentifierTable(), 247293010Sadrian PP.getSelectorTable(), PP.getBuiltinInfo(), 248293010Sadrian /*FreeMemory=*/ !getFrontendOpts().DisableFree, 249293010Sadrian /*size_reserve=*/ 0)); 250293010Sadrian} 251293010Sadrian 252293010Sadrian// ExternalASTSource 253293010Sadrian 254293010Sadrianvoid CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { 255293010Sadrian llvm::OwningPtr<ExternalASTSource> Source; 256293010Sadrian Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 257293010Sadrian getPreprocessor(), getASTContext())); 258293010Sadrian // Remember the PCHReader, but in a non-owning way. 259293010Sadrian Reader = static_cast<PCHReader*>(Source.get()); 260293010Sadrian getASTContext().setExternalSource(Source); 261293010Sadrian} 262293010Sadrian 263293010SadrianExternalASTSource * 264293010SadrianCompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, 265293010Sadrian const std::string &Sysroot, 266293010Sadrian Preprocessor &PP, 267293010Sadrian ASTContext &Context) { 268293010Sadrian llvm::OwningPtr<PCHReader> Reader; 269293010Sadrian Reader.reset(new PCHReader(PP, &Context, 270293010Sadrian Sysroot.empty() ? 0 : Sysroot.c_str())); 271293010Sadrian 272293010Sadrian switch (Reader->ReadPCH(Path)) { 273293010Sadrian case PCHReader::Success: 274293010Sadrian // Set the predefines buffer as suggested by the PCH reader. Typically, the 275293010Sadrian // predefines buffer will be empty. 276293010Sadrian PP.setPredefines(Reader->getSuggestedPredefines()); 277293010Sadrian return Reader.take(); 278293010Sadrian 279293010Sadrian case PCHReader::Failure: 280293010Sadrian // Unrecoverable failure: don't even try to process the input file. 281293010Sadrian break; 282293010Sadrian 283293010Sadrian case PCHReader::IgnorePCH: 284293010Sadrian // No suitable PCH file could be found. Return an error. 285293010Sadrian break; 286293010Sadrian } 287293010Sadrian 288293010Sadrian return 0; 289293010Sadrian} 290293010Sadrian 291293010Sadrian// Code Completion 292293010Sadrian 293293010Sadrianvoid CompilerInstance::createCodeCompletionConsumer() { 294293010Sadrian const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 295293010Sadrian CompletionConsumer.reset( 296293010Sadrian createCodeCompletionConsumer(getPreprocessor(), 297293010Sadrian Loc.FileName, Loc.Line, Loc.Column, 298293010Sadrian getFrontendOpts().DebugCodeCompletionPrinter, 299293010Sadrian getFrontendOpts().ShowMacrosInCodeCompletion, 300293010Sadrian getFrontendOpts().ShowCodePatternsInCodeCompletion, 301293010Sadrian llvm::outs())); 302293010Sadrian if (!CompletionConsumer) 303293010Sadrian return; 304293010Sadrian 305293010Sadrian if (CompletionConsumer->isOutputBinary() && 306293010Sadrian llvm::sys::Program::ChangeStdoutToBinary()) { 307293010Sadrian getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 308293010Sadrian CompletionConsumer.reset(); 309293010Sadrian } 310293010Sadrian} 311293010Sadrian 312293010Sadrianvoid CompilerInstance::createFrontendTimer() { 313293010Sadrian FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 314293010Sadrian} 315293010Sadrian 316293010SadrianCodeCompleteConsumer * 317293010SadrianCompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 318293010Sadrian const std::string &Filename, 319293010Sadrian unsigned Line, 320293010Sadrian unsigned Column, 321293010Sadrian bool UseDebugPrinter, 322293010Sadrian bool ShowMacros, 323293010Sadrian bool ShowCodePatterns, 324293010Sadrian llvm::raw_ostream &OS) { 325293010Sadrian // Tell the source manager to chop off the given file at a specific 326293010Sadrian // line and column. 327293010Sadrian const FileEntry *Entry = PP.getFileManager().getFile(Filename); 328293010Sadrian if (!Entry) { 329293010Sadrian PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 330293010Sadrian << Filename; 331293010Sadrian return 0; 332293010Sadrian } 333293010Sadrian 334293010Sadrian // Truncate the named file at the given line/column. 335293010Sadrian PP.SetCodeCompletionPoint(Entry, Line, Column); 336293010Sadrian 337293010Sadrian // Set up the creation routine for code-completion. 338293010Sadrian if (UseDebugPrinter) 339293010Sadrian return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); 340293010Sadrian else 341293010Sadrian return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); 342293010Sadrian} 343293010Sadrian 344293010Sadrian// Output Files 345293010Sadrian 346293010Sadrianvoid CompilerInstance::addOutputFile(llvm::StringRef Path, 347293010Sadrian llvm::raw_ostream *OS) { 348293010Sadrian assert(OS && "Attempt to add empty stream to output list!"); 349293010Sadrian OutputFiles.push_back(std::make_pair(Path, OS)); 350293010Sadrian} 351293010Sadrian 352293010Sadrianvoid CompilerInstance::clearOutputFiles(bool EraseFiles) { 353293010Sadrian for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator 354293010Sadrian it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 355293010Sadrian delete it->second; 356293010Sadrian if (EraseFiles && !it->first.empty()) 357293010Sadrian llvm::sys::Path(it->first).eraseFromDisk(); 358293010Sadrian } 359293010Sadrian OutputFiles.clear(); 360293010Sadrian} 361293010Sadrian 362293010Sadrianllvm::raw_fd_ostream * 363293010SadrianCompilerInstance::createDefaultOutputFile(bool Binary, 364293010Sadrian llvm::StringRef InFile, 365293010Sadrian llvm::StringRef Extension) { 366293010Sadrian return createOutputFile(getFrontendOpts().OutputFile, Binary, 367293010Sadrian InFile, Extension); 368293010Sadrian} 369293010Sadrian 370293010Sadrianllvm::raw_fd_ostream * 371293010SadrianCompilerInstance::createOutputFile(llvm::StringRef OutputPath, 372293010Sadrian bool Binary, 373293010Sadrian llvm::StringRef InFile, 374293010Sadrian llvm::StringRef Extension) { 375293010Sadrian std::string Error, OutputPathName; 376293010Sadrian llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 377293010Sadrian InFile, Extension, 378293010Sadrian &OutputPathName); 379293010Sadrian if (!OS) { 380293010Sadrian getDiagnostics().Report(diag::err_fe_unable_to_open_output) 381293010Sadrian << OutputPath << Error; 382293010Sadrian return 0; 383293010Sadrian } 384293010Sadrian 385293010Sadrian // Add the output file -- but don't try to remove "-", since this means we are 386293010Sadrian // using stdin. 387293010Sadrian addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS); 388293010Sadrian 389293010Sadrian return OS; 390293010Sadrian} 391293010Sadrian 392293010Sadrianllvm::raw_fd_ostream * 393293010SadrianCompilerInstance::createOutputFile(llvm::StringRef OutputPath, 394293010Sadrian std::string &Error, 395293010Sadrian bool Binary, 396293010Sadrian llvm::StringRef InFile, 397293010Sadrian llvm::StringRef Extension, 398293010Sadrian std::string *ResultPathName) { 399293010Sadrian std::string OutFile; 400293010Sadrian if (!OutputPath.empty()) { 401293010Sadrian OutFile = OutputPath; 402293010Sadrian } else if (InFile == "-") { 403293010Sadrian OutFile = "-"; 404293010Sadrian } else if (!Extension.empty()) { 405293010Sadrian llvm::sys::Path Path(InFile); 406293010Sadrian Path.eraseSuffix(); 407293010Sadrian Path.appendSuffix(Extension); 408293010Sadrian OutFile = Path.str(); 409293010Sadrian } else { 410293010Sadrian OutFile = "-"; 411293010Sadrian } 412293010Sadrian 413293010Sadrian llvm::OwningPtr<llvm::raw_fd_ostream> OS( 414293010Sadrian new llvm::raw_fd_ostream(OutFile.c_str(), Error, 415293010Sadrian (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 416293010Sadrian if (!Error.empty()) 417293010Sadrian return 0; 418293010Sadrian 419293010Sadrian if (ResultPathName) 420293010Sadrian *ResultPathName = OutFile; 421293010Sadrian 422293010Sadrian return OS.take(); 423293010Sadrian} 424293010Sadrian 425293010Sadrian// Initialization Utilities 426293010Sadrian 427293010Sadrianbool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) { 428293010Sadrian return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(), 429293010Sadrian getSourceManager(), getFrontendOpts()); 430293010Sadrian} 431293010Sadrian 432293010Sadrianbool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, 433293010Sadrian Diagnostic &Diags, 434293010Sadrian FileManager &FileMgr, 435293010Sadrian SourceManager &SourceMgr, 436293010Sadrian const FrontendOptions &Opts) { 437293010Sadrian // Figure out where to get and map in the main file. 438293010Sadrian if (InputFile != "-") { 439293010Sadrian const FileEntry *File = FileMgr.getFile(InputFile); 440293010Sadrian if (File) SourceMgr.createMainFileID(File, SourceLocation()); 441293010Sadrian if (SourceMgr.getMainFileID().isInvalid()) { 442293010Sadrian Diags.Report(diag::err_fe_error_reading) << InputFile; 443293010Sadrian return false; 444293010Sadrian } 445293010Sadrian } else { 446293010Sadrian llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN(); 447293010Sadrian if (SB) SourceMgr.createMainFileIDForMemBuffer(SB); 448293010Sadrian if (SourceMgr.getMainFileID().isInvalid()) { 449293010Sadrian Diags.Report(diag::err_fe_error_reading_stdin); 450293010Sadrian return false; 451293010Sadrian } 452293010Sadrian } 453293010Sadrian 454293010Sadrian return true; 455293010Sadrian} 456293010Sadrian 457293010Sadrian// High-Level Operations 458293010Sadrian 459293010Sadrianbool CompilerInstance::ExecuteAction(FrontendAction &Act) { 460293010Sadrian assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 461293010Sadrian assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 462293010Sadrian assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 463293010Sadrian 464293010Sadrian // FIXME: Take this as an argument, once all the APIs we used have moved to 465293010Sadrian // taking it as an input instead of hard-coding llvm::errs. 466293010Sadrian llvm::raw_ostream &OS = llvm::errs(); 467293010Sadrian 468293010Sadrian // Create the target instance. 469293010Sadrian setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 470293010Sadrian if (!hasTarget()) 471293010Sadrian return false; 472293010Sadrian 473293010Sadrian // Inform the target of the language options. 474293010Sadrian // 475293010Sadrian // FIXME: We shouldn't need to do this, the target should be immutable once 476293010Sadrian // created. This complexity should be lifted elsewhere. 477293010Sadrian getTarget().setForcedLangOptions(getLangOpts()); 478293010Sadrian 479293010Sadrian // Validate/process some options. 480293010Sadrian if (getHeaderSearchOpts().Verbose) 481293010Sadrian OS << "clang -cc1 version " CLANG_VERSION_STRING 482293010Sadrian << " based upon " << PACKAGE_STRING 483293010Sadrian << " hosted on " << llvm::sys::getHostTriple() << "\n"; 484293010Sadrian 485293010Sadrian if (getFrontendOpts().ShowTimers) 486293010Sadrian createFrontendTimer(); 487293010Sadrian 488293010Sadrian if (getFrontendOpts().ShowStats) 489293010Sadrian llvm::EnableStatistics(); 490293010Sadrian 491293010Sadrian for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 492293010Sadrian const std::string &InFile = getFrontendOpts().Inputs[i].second; 493293010Sadrian 494293010Sadrian // Reset the ID tables if we are reusing the SourceManager. 495293010Sadrian if (hasSourceManager()) 496293010Sadrian getSourceManager().clearIDTables(); 497293010Sadrian 498293010Sadrian if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) { 499293010Sadrian Act.Execute(); 500293010Sadrian Act.EndSourceFile(); 501293010Sadrian } 502293010Sadrian } 503293010Sadrian 504293010Sadrian if (getDiagnosticOpts().ShowCarets) { 505293010Sadrian unsigned NumWarnings = getDiagnostics().getNumWarnings(); 506293010Sadrian unsigned NumErrors = getDiagnostics().getNumErrors() - 507293010Sadrian getDiagnostics().getNumErrorsSuppressed(); 508293010Sadrian 509293010Sadrian if (NumWarnings) 510293010Sadrian OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); 511293010Sadrian if (NumWarnings && NumErrors) 512293010Sadrian OS << " and "; 513293010Sadrian if (NumErrors) 514293010Sadrian OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); 515293010Sadrian if (NumWarnings || NumErrors) 516293010Sadrian OS << " generated.\n"; 517293010Sadrian } 518293010Sadrian 519293010Sadrian if (getFrontendOpts().ShowStats && hasFileManager()) { 520293010Sadrian getFileManager().PrintStats(); 521293010Sadrian OS << "\n"; 522293010Sadrian } 523293010Sadrian 524293010Sadrian // Return the appropriate status when verifying diagnostics. 525293010Sadrian // 526293010Sadrian // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need 527293010Sadrian // this. 528293010Sadrian if (getDiagnosticOpts().VerifyDiagnostics) 529293010Sadrian return !static_cast<VerifyDiagnosticsClient&>( 530293010Sadrian getDiagnosticClient()).HadErrors(); 531293010Sadrian 532293010Sadrian return !getDiagnostics().getNumErrors(); 533293010Sadrian} 534293010Sadrian 535293010Sadrian 536293010Sadrian