CompilerInstance.cpp revision 0397af277e3bba16da1fd125ddba07415686b429
1//===--- CompilerInstance.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/CompilerInstance.h" 11#include "clang/AST/ASTConsumer.h" 12#include "clang/AST/ASTContext.h" 13#include "clang/Basic/Diagnostic.h" 14#include "clang/Basic/FileManager.h" 15#include "clang/Basic/SourceManager.h" 16#include "clang/Basic/TargetInfo.h" 17#include "clang/Basic/Version.h" 18#include "clang/Lex/HeaderSearch.h" 19#include "clang/Lex/Preprocessor.h" 20#include "clang/Lex/PTHManager.h" 21#include "clang/Frontend/ChainedDiagnosticClient.h" 22#include "clang/Frontend/FrontendAction.h" 23#include "clang/Frontend/PCHReader.h" 24#include "clang/Frontend/FrontendDiagnostic.h" 25#include "clang/Frontend/TextDiagnosticPrinter.h" 26#include "clang/Frontend/VerifyDiagnosticsClient.h" 27#include "clang/Frontend/Utils.h" 28#include "clang/Sema/CodeCompleteConsumer.h" 29#include "llvm/LLVMContext.h" 30#include "llvm/Support/MemoryBuffer.h" 31#include "llvm/Support/raw_ostream.h" 32#include "llvm/Support/Timer.h" 33#include "llvm/System/Host.h" 34#include "llvm/System/Path.h" 35#include "llvm/System/Program.h" 36using namespace clang; 37 38CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, 39 bool _OwnsLLVMContext) 40 : LLVMContext(_LLVMContext), 41 OwnsLLVMContext(_OwnsLLVMContext) { 42 } 43 44CompilerInstance::~CompilerInstance() { 45 if (OwnsLLVMContext) 46 delete LLVMContext; 47} 48 49void CompilerInstance::setDiagnostics(Diagnostic *Value) { 50 Diagnostics.reset(Value); 51} 52 53void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { 54 DiagClient.reset(Value); 55} 56 57void CompilerInstance::setTarget(TargetInfo *Value) { 58 Target.reset(Value); 59} 60 61void CompilerInstance::setFileManager(FileManager *Value) { 62 FileMgr.reset(Value); 63} 64 65void CompilerInstance::setSourceManager(SourceManager *Value) { 66 SourceMgr.reset(Value); 67} 68 69void CompilerInstance::setPreprocessor(Preprocessor *Value) { 70 PP.reset(Value); 71} 72 73void CompilerInstance::setASTContext(ASTContext *Value) { 74 Context.reset(Value); 75} 76 77void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 78 Consumer.reset(Value); 79} 80 81void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 82 CompletionConsumer.reset(Value); 83} 84 85// Diagnostics 86 87static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 88 unsigned argc, char **argv, 89 llvm::OwningPtr<DiagnosticClient> &DiagClient) { 90 std::string ErrorInfo; 91 llvm::raw_ostream *OS = 92 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo); 93 if (!ErrorInfo.empty()) { 94 // FIXME: Do not fail like this. 95 llvm::errs() << "error opening -dump-build-information file '" 96 << DiagOpts.DumpBuildInformation << "', option ignored!\n"; 97 delete OS; 98 return; 99 } 100 101 (*OS) << "clang -cc1 command line arguments: "; 102 for (unsigned i = 0; i != argc; ++i) 103 (*OS) << argv[i] << ' '; 104 (*OS) << '\n'; 105 106 // Chain in a diagnostic client which will log the diagnostics. 107 DiagnosticClient *Logger = 108 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true); 109 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger)); 110} 111 112void CompilerInstance::createDiagnostics(int Argc, char **Argv) { 113 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); 114 115 if (Diagnostics) 116 DiagClient.reset(Diagnostics->getClient()); 117} 118 119Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 120 int Argc, char **Argv) { 121 llvm::OwningPtr<Diagnostic> Diags(new Diagnostic()); 122 123 // Create the diagnostic client for reporting errors or for 124 // implementing -verify. 125 llvm::OwningPtr<DiagnosticClient> DiagClient( 126 new TextDiagnosticPrinter(llvm::errs(), Opts)); 127 128 // Chain in -verify checker, if requested. 129 if (Opts.VerifyDiagnostics) 130 DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take())); 131 132 if (!Opts.DumpBuildInformation.empty()) 133 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient); 134 135 // Configure our handling of diagnostics. 136 Diags->setClient(DiagClient.take()); 137 if (ProcessWarningOptions(*Diags, Opts)) 138 return 0; 139 140 return Diags.take(); 141} 142 143// File Manager 144 145void CompilerInstance::createFileManager() { 146 FileMgr.reset(new FileManager()); 147} 148 149// Source Manager 150 151void CompilerInstance::createSourceManager() { 152 SourceMgr.reset(new SourceManager()); 153} 154 155// Preprocessor 156 157void CompilerInstance::createPreprocessor() { 158 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 159 getPreprocessorOpts(), getHeaderSearchOpts(), 160 getDependencyOutputOpts(), getTarget(), 161 getSourceManager(), getFileManager())); 162} 163 164Preprocessor * 165CompilerInstance::createPreprocessor(Diagnostic &Diags, 166 const LangOptions &LangInfo, 167 const PreprocessorOptions &PPOpts, 168 const HeaderSearchOptions &HSOpts, 169 const DependencyOutputOptions &DepOpts, 170 const TargetInfo &Target, 171 SourceManager &SourceMgr, 172 FileManager &FileMgr) { 173 // Create a PTH manager if we are using some form of a token cache. 174 PTHManager *PTHMgr = 0; 175 if (!PPOpts.TokenCache.empty()) 176 PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags); 177 178 // Create the Preprocessor. 179 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 180 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 181 SourceMgr, *HeaderInfo, PTHMgr, 182 /*OwnsHeaderSearch=*/true); 183 184 // Note that this is different then passing PTHMgr to Preprocessor's ctor. 185 // That argument is used as the IdentifierInfoLookup argument to 186 // IdentifierTable's ctor. 187 if (PTHMgr) { 188 PTHMgr->setPreprocessor(PP); 189 PP->setPTHManager(PTHMgr); 190 } 191 192 InitializePreprocessor(*PP, PPOpts, HSOpts); 193 194 // Handle generating dependencies, if requested. 195 if (!DepOpts.OutputFile.empty()) 196 AttachDependencyFileGen(*PP, DepOpts); 197 198 return PP; 199} 200 201// ASTContext 202 203void CompilerInstance::createASTContext() { 204 Preprocessor &PP = getPreprocessor(); 205 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), 206 getTarget(), PP.getIdentifierTable(), 207 PP.getSelectorTable(), PP.getBuiltinInfo(), 208 /*FreeMemory=*/ !getFrontendOpts().DisableFree, 209 /*size_reserve=*/ 0)); 210} 211 212// ExternalASTSource 213 214void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { 215 llvm::OwningPtr<ExternalASTSource> Source; 216 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 217 getPreprocessor(), getASTContext())); 218 getASTContext().setExternalSource(Source); 219} 220 221ExternalASTSource * 222CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, 223 const std::string &Sysroot, 224 Preprocessor &PP, 225 ASTContext &Context) { 226 llvm::OwningPtr<PCHReader> Reader; 227 Reader.reset(new PCHReader(PP, &Context, 228 Sysroot.empty() ? 0 : Sysroot.c_str())); 229 230 switch (Reader->ReadPCH(Path)) { 231 case PCHReader::Success: 232 // Set the predefines buffer as suggested by the PCH reader. Typically, the 233 // predefines buffer will be empty. 234 PP.setPredefines(Reader->getSuggestedPredefines()); 235 return Reader.take(); 236 237 case PCHReader::Failure: 238 // Unrecoverable failure: don't even try to process the input file. 239 break; 240 241 case PCHReader::IgnorePCH: 242 // No suitable PCH file could be found. Return an error. 243 break; 244 } 245 246 return 0; 247} 248 249// Code Completion 250 251void CompilerInstance::createCodeCompletionConsumer() { 252 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 253 CompletionConsumer.reset( 254 createCodeCompletionConsumer(getPreprocessor(), 255 Loc.FileName, Loc.Line, Loc.Column, 256 getFrontendOpts().DebugCodeCompletionPrinter, 257 getFrontendOpts().ShowMacrosInCodeCompletion, 258 llvm::outs())); 259 260 if (CompletionConsumer->isOutputBinary() && 261 llvm::sys::Program::ChangeStdoutToBinary()) { 262 getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 263 CompletionConsumer.reset(); 264 } 265} 266 267void CompilerInstance::createFrontendTimer() { 268 FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 269} 270 271CodeCompleteConsumer * 272CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 273 const std::string &Filename, 274 unsigned Line, 275 unsigned Column, 276 bool UseDebugPrinter, 277 bool ShowMacros, 278 llvm::raw_ostream &OS) { 279 // Tell the source manager to chop off the given file at a specific 280 // line and column. 281 const FileEntry *Entry = PP.getFileManager().getFile(Filename); 282 if (!Entry) { 283 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 284 << Filename; 285 return 0; 286 } 287 288 // Truncate the named file at the given line/column. 289 PP.SetCodeCompletionPoint(Entry, Line, Column); 290 291 // Set up the creation routine for code-completion. 292 if (UseDebugPrinter) 293 return new PrintingCodeCompleteConsumer(ShowMacros, OS); 294 else 295 return new CIndexCodeCompleteConsumer(ShowMacros, OS); 296} 297 298// Output Files 299 300void CompilerInstance::addOutputFile(llvm::StringRef Path, 301 llvm::raw_ostream *OS) { 302 assert(OS && "Attempt to add empty stream to output list!"); 303 OutputFiles.push_back(std::make_pair(Path, OS)); 304} 305 306void CompilerInstance::ClearOutputFiles(bool EraseFiles) { 307 for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator 308 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 309 delete it->second; 310 if (EraseFiles && !it->first.empty()) 311 llvm::sys::Path(it->first).eraseFromDisk(); 312 } 313 OutputFiles.clear(); 314} 315 316llvm::raw_fd_ostream * 317CompilerInstance::createDefaultOutputFile(bool Binary, 318 llvm::StringRef InFile, 319 llvm::StringRef Extension) { 320 return createOutputFile(getFrontendOpts().OutputFile, Binary, 321 InFile, Extension); 322} 323 324llvm::raw_fd_ostream * 325CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 326 bool Binary, 327 llvm::StringRef InFile, 328 llvm::StringRef Extension) { 329 std::string Error, OutputPathName; 330 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 331 InFile, Extension, 332 &OutputPathName); 333 if (!OS) { 334 getDiagnostics().Report(diag::err_fe_unable_to_open_output) 335 << OutputPath << Error; 336 return 0; 337 } 338 339 // Add the output file -- but don't try to remove "-", since this means we are 340 // using stdin. 341 addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS); 342 343 return OS; 344} 345 346llvm::raw_fd_ostream * 347CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 348 std::string &Error, 349 bool Binary, 350 llvm::StringRef InFile, 351 llvm::StringRef Extension, 352 std::string *ResultPathName) { 353 std::string OutFile; 354 if (!OutputPath.empty()) { 355 OutFile = OutputPath; 356 } else if (InFile == "-") { 357 OutFile = "-"; 358 } else if (!Extension.empty()) { 359 llvm::sys::Path Path(InFile); 360 Path.eraseSuffix(); 361 Path.appendSuffix(Extension); 362 OutFile = Path.str(); 363 } else { 364 OutFile = "-"; 365 } 366 367 llvm::OwningPtr<llvm::raw_fd_ostream> OS( 368 new llvm::raw_fd_ostream(OutFile.c_str(), Error, 369 (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 370 if (!Error.empty()) 371 return 0; 372 373 if (ResultPathName) 374 *ResultPathName = OutFile; 375 376 return OS.take(); 377} 378 379// Initialization Utilities 380 381bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) { 382 return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(), 383 getSourceManager(), getFrontendOpts()); 384} 385 386bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, 387 Diagnostic &Diags, 388 FileManager &FileMgr, 389 SourceManager &SourceMgr, 390 const FrontendOptions &Opts) { 391 // Figure out where to get and map in the main file. 392 if (Opts.EmptyInputOnly) { 393 const char *EmptyStr = ""; 394 llvm::MemoryBuffer *SB = 395 llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>"); 396 SourceMgr.createMainFileIDForMemBuffer(SB); 397 } else if (InputFile != "-") { 398 const FileEntry *File = FileMgr.getFile(InputFile); 399 if (File) SourceMgr.createMainFileID(File, SourceLocation()); 400 if (SourceMgr.getMainFileID().isInvalid()) { 401 Diags.Report(diag::err_fe_error_reading) << InputFile; 402 return false; 403 } 404 } else { 405 llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN(); 406 SourceMgr.createMainFileIDForMemBuffer(SB); 407 if (SourceMgr.getMainFileID().isInvalid()) { 408 Diags.Report(diag::err_fe_error_reading_stdin); 409 return false; 410 } 411 } 412 413 return true; 414} 415 416// High-Level Operations 417 418bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 419 assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 420 assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 421 assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 422 423 // FIXME: Take this as an argument, once all the APIs we used have moved to 424 // taking it as an input instead of hard-coding llvm::errs. 425 llvm::raw_ostream &OS = llvm::errs(); 426 427 // Create the target instance. 428 setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 429 if (!hasTarget()) 430 return false; 431 432 // Inform the target of the language options. 433 // 434 // FIXME: We shouldn't need to do this, the target should be immutable once 435 // created. This complexity should be lifted elsewhere. 436 getTarget().setForcedLangOptions(getLangOpts()); 437 438 // Validate/process some options. 439 if (getHeaderSearchOpts().Verbose) 440 OS << "clang -cc1 version " CLANG_VERSION_STRING 441 << " based upon " << PACKAGE_STRING 442 << " hosted on " << llvm::sys::getHostTriple() << "\n"; 443 444 if (getFrontendOpts().ShowTimers) 445 createFrontendTimer(); 446 447 for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 448 const std::string &InFile = getFrontendOpts().Inputs[i].second; 449 450 // If we aren't using an AST file, setup the file and source managers and 451 // the preprocessor. 452 bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; 453 if (!IsAST) { 454 if (!i) { 455 // Create a file manager object to provide access to and cache the 456 // filesystem. 457 createFileManager(); 458 459 // Create the source manager. 460 createSourceManager(); 461 } else { 462 // Reset the ID tables if we are reusing the SourceManager. 463 getSourceManager().clearIDTables(); 464 } 465 466 // Create the preprocessor. 467 createPreprocessor(); 468 } 469 470 if (Act.BeginSourceFile(*this, InFile, IsAST)) { 471 Act.Execute(); 472 Act.EndSourceFile(); 473 } 474 } 475 476 if (getDiagnosticOpts().ShowCarets) 477 if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics()) 478 OS << NumDiagnostics << " diagnostic" 479 << (NumDiagnostics == 1 ? "" : "s") 480 << " generated.\n"; 481 482 if (getFrontendOpts().ShowStats) { 483 getFileManager().PrintStats(); 484 OS << "\n"; 485 } 486 487 // Return the appropriate status when verifying diagnostics. 488 // 489 // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need 490 // this. 491 if (getDiagnosticOpts().VerifyDiagnostics) 492 return !static_cast<VerifyDiagnosticsClient&>( 493 getDiagnosticClient()).HadErrors(); 494 495 return !getDiagnostics().getNumErrors(); 496} 497 498 499