1636404a3SDaniel Dunbar //===--- CompilerInstance.cpp ---------------------------------------------===// 2636404a3SDaniel Dunbar // 3636404a3SDaniel Dunbar // The LLVM Compiler Infrastructure 4636404a3SDaniel Dunbar // 5636404a3SDaniel Dunbar // This file is distributed under the University of Illinois Open Source 6636404a3SDaniel Dunbar // License. See LICENSE.TXT for details. 7636404a3SDaniel Dunbar // 8636404a3SDaniel Dunbar //===----------------------------------------------------------------------===// 9636404a3SDaniel Dunbar 10636404a3SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h" 1156d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h" 12df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h" 13636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h" 14546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h" 15546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h" 16636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h" 174f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h" 18aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h" 19aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h" 20aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.h" 217d75afc5SDaniel Dunbar #include "clang/Frontend/ChainedDiagnosticClient.h" 224f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h" 23599313efSDaniel Dunbar #include "clang/Frontend/PCHReader.h" 24f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h" 257d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h" 2650ec0da0SDaniel Dunbar #include "clang/Frontend/VerifyDiagnosticsClient.h" 27aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h" 28f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h" 29636404a3SDaniel Dunbar #include "llvm/LLVMContext.h" 30409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h" 317d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h" 325505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h" 334f2bc55dSDaniel Dunbar #include "llvm/System/Host.h" 34566eeb2dSDaniel Dunbar #include "llvm/System/Path.h" 35f09935f1SDouglas Gregor #include "llvm/System/Program.h" 36636404a3SDaniel Dunbar using namespace clang; 37636404a3SDaniel Dunbar 38e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance() 39e922d9bdSDaniel Dunbar : Invocation(new CompilerInvocation()) { 40636404a3SDaniel Dunbar } 41636404a3SDaniel Dunbar 42636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() { 43e922d9bdSDaniel Dunbar } 44e922d9bdSDaniel Dunbar 45e922d9bdSDaniel Dunbar void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) { 46e922d9bdSDaniel Dunbar LLVMContext.reset(Value); 47636404a3SDaniel Dunbar } 48546a676aSDaniel Dunbar 4968242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) { 5068242254SDaniel Dunbar Invocation.reset(Value); 5168242254SDaniel Dunbar } 5268242254SDaniel Dunbar 53e01dc86dSDaniel Dunbar void CompilerInstance::setDiagnostics(Diagnostic *Value) { 54e01dc86dSDaniel Dunbar Diagnostics.reset(Value); 55e01dc86dSDaniel Dunbar } 56e01dc86dSDaniel Dunbar 57e01dc86dSDaniel Dunbar void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { 58e01dc86dSDaniel Dunbar DiagClient.reset(Value); 59e01dc86dSDaniel Dunbar } 60e01dc86dSDaniel Dunbar 61e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) { 62e01dc86dSDaniel Dunbar Target.reset(Value); 63e01dc86dSDaniel Dunbar } 64e01dc86dSDaniel Dunbar 65e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) { 66e01dc86dSDaniel Dunbar FileMgr.reset(Value); 67e01dc86dSDaniel Dunbar } 68e01dc86dSDaniel Dunbar 69e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) { 70e01dc86dSDaniel Dunbar SourceMgr.reset(Value); 71e01dc86dSDaniel Dunbar } 72e01dc86dSDaniel Dunbar 73e01dc86dSDaniel Dunbar void CompilerInstance::setPreprocessor(Preprocessor *Value) { 74e01dc86dSDaniel Dunbar PP.reset(Value); 75e01dc86dSDaniel Dunbar } 76e01dc86dSDaniel Dunbar 77e01dc86dSDaniel Dunbar void CompilerInstance::setASTContext(ASTContext *Value) { 78e01dc86dSDaniel Dunbar Context.reset(Value); 79e01dc86dSDaniel Dunbar } 80e01dc86dSDaniel Dunbar 8156d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 8256d9c293SDaniel Dunbar Consumer.reset(Value); 8356d9c293SDaniel Dunbar } 8456d9c293SDaniel Dunbar 85e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 86e01dc86dSDaniel Dunbar CompletionConsumer.reset(Value); 87e01dc86dSDaniel Dunbar } 88e01dc86dSDaniel Dunbar 897d75afc5SDaniel Dunbar // Diagnostics 90ac0605e9SDouglas Gregor namespace { 91ac0605e9SDouglas Gregor class BinaryDiagnosticSerializer : public DiagnosticClient { 92ac0605e9SDouglas Gregor llvm::raw_ostream &OS; 93ac0605e9SDouglas Gregor SourceManager *SourceMgr; 94ac0605e9SDouglas Gregor public: 95ac0605e9SDouglas Gregor explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS) 96ac0605e9SDouglas Gregor : OS(OS), SourceMgr(0) { } 97ac0605e9SDouglas Gregor 98ac0605e9SDouglas Gregor virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, 99ac0605e9SDouglas Gregor const DiagnosticInfo &Info); 100ac0605e9SDouglas Gregor }; 101ac0605e9SDouglas Gregor } 102ac0605e9SDouglas Gregor 103ac0605e9SDouglas Gregor void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel, 104ac0605e9SDouglas Gregor const DiagnosticInfo &Info) { 10533cdd810SDouglas Gregor StoredDiagnostic(DiagLevel, Info).Serialize(OS); 106ac0605e9SDouglas Gregor } 1077d75afc5SDaniel Dunbar 1087d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 1097d75afc5SDaniel Dunbar unsigned argc, char **argv, 1107d75afc5SDaniel Dunbar llvm::OwningPtr<DiagnosticClient> &DiagClient) { 1117d75afc5SDaniel Dunbar std::string ErrorInfo; 1127d75afc5SDaniel Dunbar llvm::raw_ostream *OS = 1137d75afc5SDaniel Dunbar new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo); 1147d75afc5SDaniel Dunbar if (!ErrorInfo.empty()) { 1157d75afc5SDaniel Dunbar // FIXME: Do not fail like this. 1167d75afc5SDaniel Dunbar llvm::errs() << "error opening -dump-build-information file '" 1177d75afc5SDaniel Dunbar << DiagOpts.DumpBuildInformation << "', option ignored!\n"; 1187d75afc5SDaniel Dunbar delete OS; 1197d75afc5SDaniel Dunbar return; 1207d75afc5SDaniel Dunbar } 1217d75afc5SDaniel Dunbar 122520d1e6cSDaniel Dunbar (*OS) << "clang -cc1 command line arguments: "; 1237d75afc5SDaniel Dunbar for (unsigned i = 0; i != argc; ++i) 1247d75afc5SDaniel Dunbar (*OS) << argv[i] << ' '; 1257d75afc5SDaniel Dunbar (*OS) << '\n'; 1267d75afc5SDaniel Dunbar 1277d75afc5SDaniel Dunbar // Chain in a diagnostic client which will log the diagnostics. 1287d75afc5SDaniel Dunbar DiagnosticClient *Logger = 1297d75afc5SDaniel Dunbar new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true); 1307d75afc5SDaniel Dunbar DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger)); 1317d75afc5SDaniel Dunbar } 1327d75afc5SDaniel Dunbar 1337d75afc5SDaniel Dunbar void CompilerInstance::createDiagnostics(int Argc, char **Argv) { 1347d75afc5SDaniel Dunbar Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); 1357d75afc5SDaniel Dunbar 1367d75afc5SDaniel Dunbar if (Diagnostics) 1377d75afc5SDaniel Dunbar DiagClient.reset(Diagnostics->getClient()); 1387d75afc5SDaniel Dunbar } 1397d75afc5SDaniel Dunbar 1407d75afc5SDaniel Dunbar Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 1417d75afc5SDaniel Dunbar int Argc, char **Argv) { 1421b39a2edSDaniel Dunbar llvm::OwningPtr<Diagnostic> Diags(new Diagnostic()); 1431b39a2edSDaniel Dunbar 1447d75afc5SDaniel Dunbar // Create the diagnostic client for reporting errors or for 1457d75afc5SDaniel Dunbar // implementing -verify. 146ac0605e9SDouglas Gregor llvm::OwningPtr<DiagnosticClient> DiagClient; 147ac0605e9SDouglas Gregor if (Opts.BinaryOutput) { 148ac0605e9SDouglas Gregor if (llvm::sys::Program::ChangeStderrToBinary()) { 149ac0605e9SDouglas Gregor // We weren't able to set standard error to binary, which is a 150ac0605e9SDouglas Gregor // bit of a problem. So, just create a text diagnostic printer 151ac0605e9SDouglas Gregor // to complain about this problem, and pretend that the user 152ac0605e9SDouglas Gregor // didn't try to use binary output. 153ac0605e9SDouglas Gregor DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 154ac0605e9SDouglas Gregor Diags->setClient(DiagClient.take()); 155ac0605e9SDouglas Gregor Diags->Report(diag::err_fe_stderr_binary); 156ac0605e9SDouglas Gregor return Diags.take(); 157ac0605e9SDouglas Gregor } else { 158ac0605e9SDouglas Gregor DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs())); 159ac0605e9SDouglas Gregor } 160ac0605e9SDouglas Gregor } else { 161ac0605e9SDouglas Gregor DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 162ac0605e9SDouglas Gregor } 16350ec0da0SDaniel Dunbar 16450ec0da0SDaniel Dunbar // Chain in -verify checker, if requested. 16550ec0da0SDaniel Dunbar if (Opts.VerifyDiagnostics) 1661b39a2edSDaniel Dunbar DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take())); 1677d75afc5SDaniel Dunbar 1687d75afc5SDaniel Dunbar if (!Opts.DumpBuildInformation.empty()) 1697d75afc5SDaniel Dunbar SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient); 1707d75afc5SDaniel Dunbar 1717d75afc5SDaniel Dunbar // Configure our handling of diagnostics. 1721b39a2edSDaniel Dunbar Diags->setClient(DiagClient.take()); 1737d75afc5SDaniel Dunbar if (ProcessWarningOptions(*Diags, Opts)) 1747d75afc5SDaniel Dunbar return 0; 1757d75afc5SDaniel Dunbar 1761b39a2edSDaniel Dunbar return Diags.take(); 1777d75afc5SDaniel Dunbar } 1787d75afc5SDaniel Dunbar 1797d75afc5SDaniel Dunbar // File Manager 1807d75afc5SDaniel Dunbar 181546a676aSDaniel Dunbar void CompilerInstance::createFileManager() { 182546a676aSDaniel Dunbar FileMgr.reset(new FileManager()); 183546a676aSDaniel Dunbar } 184546a676aSDaniel Dunbar 1857d75afc5SDaniel Dunbar // Source Manager 1867d75afc5SDaniel Dunbar 187546a676aSDaniel Dunbar void CompilerInstance::createSourceManager() { 188e0fbb83bSDouglas Gregor SourceMgr.reset(new SourceManager(getDiagnostics())); 189546a676aSDaniel Dunbar } 190aaa148fdSDaniel Dunbar 1917d75afc5SDaniel Dunbar // Preprocessor 1927d75afc5SDaniel Dunbar 193aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() { 194aaa148fdSDaniel Dunbar PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 195aaa148fdSDaniel Dunbar getPreprocessorOpts(), getHeaderSearchOpts(), 196aaa148fdSDaniel Dunbar getDependencyOutputOpts(), getTarget(), 1973f7b8b27SFariborz Jahanian getFrontendOpts(), getSourceManager(), 1983f7b8b27SFariborz Jahanian getFileManager())); 199aaa148fdSDaniel Dunbar } 200aaa148fdSDaniel Dunbar 201aaa148fdSDaniel Dunbar Preprocessor * 202aaa148fdSDaniel Dunbar CompilerInstance::createPreprocessor(Diagnostic &Diags, 203aaa148fdSDaniel Dunbar const LangOptions &LangInfo, 204aaa148fdSDaniel Dunbar const PreprocessorOptions &PPOpts, 205aaa148fdSDaniel Dunbar const HeaderSearchOptions &HSOpts, 206aaa148fdSDaniel Dunbar const DependencyOutputOptions &DepOpts, 207aaa148fdSDaniel Dunbar const TargetInfo &Target, 2083f7b8b27SFariborz Jahanian const FrontendOptions &FEOpts, 209aaa148fdSDaniel Dunbar SourceManager &SourceMgr, 210aaa148fdSDaniel Dunbar FileManager &FileMgr) { 211aaa148fdSDaniel Dunbar // Create a PTH manager if we are using some form of a token cache. 212aaa148fdSDaniel Dunbar PTHManager *PTHMgr = 0; 213d6ea9028SDaniel Dunbar if (!PPOpts.TokenCache.empty()) 214d6ea9028SDaniel Dunbar PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags); 215aaa148fdSDaniel Dunbar 216aaa148fdSDaniel Dunbar // Create the Preprocessor. 217aaa148fdSDaniel Dunbar HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 218aaa148fdSDaniel Dunbar Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 219aaa148fdSDaniel Dunbar SourceMgr, *HeaderInfo, PTHMgr, 220aaa148fdSDaniel Dunbar /*OwnsHeaderSearch=*/true); 221aaa148fdSDaniel Dunbar 222aaa148fdSDaniel Dunbar // Note that this is different then passing PTHMgr to Preprocessor's ctor. 223aaa148fdSDaniel Dunbar // That argument is used as the IdentifierInfoLookup argument to 224aaa148fdSDaniel Dunbar // IdentifierTable's ctor. 225aaa148fdSDaniel Dunbar if (PTHMgr) { 226aaa148fdSDaniel Dunbar PTHMgr->setPreprocessor(PP); 227aaa148fdSDaniel Dunbar PP->setPTHManager(PTHMgr); 228aaa148fdSDaniel Dunbar } 229aaa148fdSDaniel Dunbar 2303f7b8b27SFariborz Jahanian InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts); 231aaa148fdSDaniel Dunbar 232aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested. 233aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty()) 234aaa148fdSDaniel Dunbar AttachDependencyFileGen(*PP, DepOpts); 235aaa148fdSDaniel Dunbar 236aaa148fdSDaniel Dunbar return PP; 237aaa148fdSDaniel Dunbar } 238df3e30c4SDaniel Dunbar 239df3e30c4SDaniel Dunbar // ASTContext 240df3e30c4SDaniel Dunbar 241df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() { 242df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor(); 243df3e30c4SDaniel Dunbar Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), 244df3e30c4SDaniel Dunbar getTarget(), PP.getIdentifierTable(), 245df3e30c4SDaniel Dunbar PP.getSelectorTable(), PP.getBuiltinInfo(), 246df3e30c4SDaniel Dunbar /*FreeMemory=*/ !getFrontendOpts().DisableFree, 247df3e30c4SDaniel Dunbar /*size_reserve=*/ 0)); 248df3e30c4SDaniel Dunbar } 249599313efSDaniel Dunbar 250599313efSDaniel Dunbar // ExternalASTSource 251599313efSDaniel Dunbar 252599313efSDaniel Dunbar void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { 253599313efSDaniel Dunbar llvm::OwningPtr<ExternalASTSource> Source; 254599313efSDaniel Dunbar Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 255599313efSDaniel Dunbar getPreprocessor(), getASTContext())); 256599313efSDaniel Dunbar getASTContext().setExternalSource(Source); 257599313efSDaniel Dunbar } 258599313efSDaniel Dunbar 259599313efSDaniel Dunbar ExternalASTSource * 260599313efSDaniel Dunbar CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, 261599313efSDaniel Dunbar const std::string &Sysroot, 262599313efSDaniel Dunbar Preprocessor &PP, 263599313efSDaniel Dunbar ASTContext &Context) { 264599313efSDaniel Dunbar llvm::OwningPtr<PCHReader> Reader; 265599313efSDaniel Dunbar Reader.reset(new PCHReader(PP, &Context, 266599313efSDaniel Dunbar Sysroot.empty() ? 0 : Sysroot.c_str())); 267599313efSDaniel Dunbar 268599313efSDaniel Dunbar switch (Reader->ReadPCH(Path)) { 269599313efSDaniel Dunbar case PCHReader::Success: 270599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the 271599313efSDaniel Dunbar // predefines buffer will be empty. 272599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines()); 273599313efSDaniel Dunbar return Reader.take(); 274599313efSDaniel Dunbar 275599313efSDaniel Dunbar case PCHReader::Failure: 276599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file. 277599313efSDaniel Dunbar break; 278599313efSDaniel Dunbar 279599313efSDaniel Dunbar case PCHReader::IgnorePCH: 280599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error. 281599313efSDaniel Dunbar break; 282599313efSDaniel Dunbar } 283599313efSDaniel Dunbar 284599313efSDaniel Dunbar return 0; 285599313efSDaniel Dunbar } 286f7093b5aSDaniel Dunbar 287f7093b5aSDaniel Dunbar // Code Completion 288f7093b5aSDaniel Dunbar 289f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() { 290f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 291f7093b5aSDaniel Dunbar CompletionConsumer.reset( 292f7093b5aSDaniel Dunbar createCodeCompletionConsumer(getPreprocessor(), 293f7093b5aSDaniel Dunbar Loc.FileName, Loc.Line, Loc.Column, 294f7093b5aSDaniel Dunbar getFrontendOpts().DebugCodeCompletionPrinter, 295f7093b5aSDaniel Dunbar getFrontendOpts().ShowMacrosInCodeCompletion, 296f7093b5aSDaniel Dunbar llvm::outs())); 297*00a0cf70SDouglas Gregor if (!CompletionConsumer) 298*00a0cf70SDouglas Gregor return; 299f09935f1SDouglas Gregor 300f09935f1SDouglas Gregor if (CompletionConsumer->isOutputBinary() && 301f09935f1SDouglas Gregor llvm::sys::Program::ChangeStdoutToBinary()) { 302f09935f1SDouglas Gregor getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); 303f09935f1SDouglas Gregor CompletionConsumer.reset(); 304f09935f1SDouglas Gregor } 305f7093b5aSDaniel Dunbar } 306f7093b5aSDaniel Dunbar 3075505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() { 3085505dff8SKovarththanan Rajaratnam FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); 3095505dff8SKovarththanan Rajaratnam } 3105505dff8SKovarththanan Rajaratnam 311f7093b5aSDaniel Dunbar CodeCompleteConsumer * 312f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 313f7093b5aSDaniel Dunbar const std::string &Filename, 314f7093b5aSDaniel Dunbar unsigned Line, 315f7093b5aSDaniel Dunbar unsigned Column, 316f7093b5aSDaniel Dunbar bool UseDebugPrinter, 317f7093b5aSDaniel Dunbar bool ShowMacros, 318f7093b5aSDaniel Dunbar llvm::raw_ostream &OS) { 319f7093b5aSDaniel Dunbar // Tell the source manager to chop off the given file at a specific 320f7093b5aSDaniel Dunbar // line and column. 321f7093b5aSDaniel Dunbar const FileEntry *Entry = PP.getFileManager().getFile(Filename); 322f7093b5aSDaniel Dunbar if (!Entry) { 323f7093b5aSDaniel Dunbar PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 324f7093b5aSDaniel Dunbar << Filename; 325f7093b5aSDaniel Dunbar return 0; 326f7093b5aSDaniel Dunbar } 327f7093b5aSDaniel Dunbar 328f7093b5aSDaniel Dunbar // Truncate the named file at the given line/column. 32953ad6b94SDouglas Gregor PP.SetCodeCompletionPoint(Entry, Line, Column); 330f7093b5aSDaniel Dunbar 331f7093b5aSDaniel Dunbar // Set up the creation routine for code-completion. 332f7093b5aSDaniel Dunbar if (UseDebugPrinter) 333f7093b5aSDaniel Dunbar return new PrintingCodeCompleteConsumer(ShowMacros, OS); 334f7093b5aSDaniel Dunbar else 335f7093b5aSDaniel Dunbar return new CIndexCodeCompleteConsumer(ShowMacros, OS); 336f7093b5aSDaniel Dunbar } 337566eeb2dSDaniel Dunbar 338566eeb2dSDaniel Dunbar // Output Files 339566eeb2dSDaniel Dunbar 340566eeb2dSDaniel Dunbar void CompilerInstance::addOutputFile(llvm::StringRef Path, 341566eeb2dSDaniel Dunbar llvm::raw_ostream *OS) { 342566eeb2dSDaniel Dunbar assert(OS && "Attempt to add empty stream to output list!"); 343566eeb2dSDaniel Dunbar OutputFiles.push_back(std::make_pair(Path, OS)); 344566eeb2dSDaniel Dunbar } 345566eeb2dSDaniel Dunbar 3461c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) { 347566eeb2dSDaniel Dunbar for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator 348566eeb2dSDaniel Dunbar it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 349566eeb2dSDaniel Dunbar delete it->second; 350566eeb2dSDaniel Dunbar if (EraseFiles && !it->first.empty()) 351566eeb2dSDaniel Dunbar llvm::sys::Path(it->first).eraseFromDisk(); 352566eeb2dSDaniel Dunbar } 353566eeb2dSDaniel Dunbar OutputFiles.clear(); 354566eeb2dSDaniel Dunbar } 355566eeb2dSDaniel Dunbar 356420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 357420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary, 358420b0f1bSDaniel Dunbar llvm::StringRef InFile, 359420b0f1bSDaniel Dunbar llvm::StringRef Extension) { 360420b0f1bSDaniel Dunbar return createOutputFile(getFrontendOpts().OutputFile, Binary, 361420b0f1bSDaniel Dunbar InFile, Extension); 362420b0f1bSDaniel Dunbar } 363420b0f1bSDaniel Dunbar 364420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 365420b0f1bSDaniel Dunbar CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 366420b0f1bSDaniel Dunbar bool Binary, 367420b0f1bSDaniel Dunbar llvm::StringRef InFile, 368420b0f1bSDaniel Dunbar llvm::StringRef Extension) { 369420b0f1bSDaniel Dunbar std::string Error, OutputPathName; 370420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 371420b0f1bSDaniel Dunbar InFile, Extension, 372420b0f1bSDaniel Dunbar &OutputPathName); 373420b0f1bSDaniel Dunbar if (!OS) { 3747554699aSDaniel Dunbar getDiagnostics().Report(diag::err_fe_unable_to_open_output) 3757554699aSDaniel Dunbar << OutputPath << Error; 3767554699aSDaniel Dunbar return 0; 377420b0f1bSDaniel Dunbar } 378420b0f1bSDaniel Dunbar 379420b0f1bSDaniel Dunbar // Add the output file -- but don't try to remove "-", since this means we are 380420b0f1bSDaniel Dunbar // using stdin. 381420b0f1bSDaniel Dunbar addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS); 382420b0f1bSDaniel Dunbar 383420b0f1bSDaniel Dunbar return OS; 384420b0f1bSDaniel Dunbar } 385420b0f1bSDaniel Dunbar 386420b0f1bSDaniel Dunbar llvm::raw_fd_ostream * 387420b0f1bSDaniel Dunbar CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 388420b0f1bSDaniel Dunbar std::string &Error, 389420b0f1bSDaniel Dunbar bool Binary, 390420b0f1bSDaniel Dunbar llvm::StringRef InFile, 391420b0f1bSDaniel Dunbar llvm::StringRef Extension, 392420b0f1bSDaniel Dunbar std::string *ResultPathName) { 393420b0f1bSDaniel Dunbar std::string OutFile; 394420b0f1bSDaniel Dunbar if (!OutputPath.empty()) { 395420b0f1bSDaniel Dunbar OutFile = OutputPath; 396420b0f1bSDaniel Dunbar } else if (InFile == "-") { 397420b0f1bSDaniel Dunbar OutFile = "-"; 398420b0f1bSDaniel Dunbar } else if (!Extension.empty()) { 399420b0f1bSDaniel Dunbar llvm::sys::Path Path(InFile); 400420b0f1bSDaniel Dunbar Path.eraseSuffix(); 401420b0f1bSDaniel Dunbar Path.appendSuffix(Extension); 402420b0f1bSDaniel Dunbar OutFile = Path.str(); 403420b0f1bSDaniel Dunbar } else { 404420b0f1bSDaniel Dunbar OutFile = "-"; 405420b0f1bSDaniel Dunbar } 406420b0f1bSDaniel Dunbar 4072eaef18eSDaniel Dunbar llvm::OwningPtr<llvm::raw_fd_ostream> OS( 408420b0f1bSDaniel Dunbar new llvm::raw_fd_ostream(OutFile.c_str(), Error, 4092eaef18eSDaniel Dunbar (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); 4102eaef18eSDaniel Dunbar if (!Error.empty()) 411420b0f1bSDaniel Dunbar return 0; 412420b0f1bSDaniel Dunbar 413420b0f1bSDaniel Dunbar if (ResultPathName) 414420b0f1bSDaniel Dunbar *ResultPathName = OutFile; 415420b0f1bSDaniel Dunbar 4162eaef18eSDaniel Dunbar return OS.take(); 417420b0f1bSDaniel Dunbar } 418409e890fSDaniel Dunbar 419409e890fSDaniel Dunbar // Initialization Utilities 420409e890fSDaniel Dunbar 421409e890fSDaniel Dunbar bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) { 422409e890fSDaniel Dunbar return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(), 423409e890fSDaniel Dunbar getSourceManager(), getFrontendOpts()); 424409e890fSDaniel Dunbar } 425409e890fSDaniel Dunbar 426409e890fSDaniel Dunbar bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, 427409e890fSDaniel Dunbar Diagnostic &Diags, 428409e890fSDaniel Dunbar FileManager &FileMgr, 429409e890fSDaniel Dunbar SourceManager &SourceMgr, 430409e890fSDaniel Dunbar const FrontendOptions &Opts) { 431409e890fSDaniel Dunbar // Figure out where to get and map in the main file. 432409e890fSDaniel Dunbar if (Opts.EmptyInputOnly) { 433409e890fSDaniel Dunbar const char *EmptyStr = ""; 434409e890fSDaniel Dunbar llvm::MemoryBuffer *SB = 435409e890fSDaniel Dunbar llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>"); 436409e890fSDaniel Dunbar SourceMgr.createMainFileIDForMemBuffer(SB); 437409e890fSDaniel Dunbar } else if (InputFile != "-") { 438409e890fSDaniel Dunbar const FileEntry *File = FileMgr.getFile(InputFile); 439409e890fSDaniel Dunbar if (File) SourceMgr.createMainFileID(File, SourceLocation()); 440409e890fSDaniel Dunbar if (SourceMgr.getMainFileID().isInvalid()) { 441409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile; 442409e890fSDaniel Dunbar return false; 443409e890fSDaniel Dunbar } 444409e890fSDaniel Dunbar } else { 445409e890fSDaniel Dunbar llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN(); 446409e890fSDaniel Dunbar SourceMgr.createMainFileIDForMemBuffer(SB); 447409e890fSDaniel Dunbar if (SourceMgr.getMainFileID().isInvalid()) { 448409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading_stdin); 449409e890fSDaniel Dunbar return false; 450409e890fSDaniel Dunbar } 451409e890fSDaniel Dunbar } 452409e890fSDaniel Dunbar 453409e890fSDaniel Dunbar return true; 454409e890fSDaniel Dunbar } 4554f2bc55dSDaniel Dunbar 4564f2bc55dSDaniel Dunbar // High-Level Operations 4574f2bc55dSDaniel Dunbar 4584f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) { 4594f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); 4604f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); 4614f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); 4624f2bc55dSDaniel Dunbar 4634f2bc55dSDaniel Dunbar // FIXME: Take this as an argument, once all the APIs we used have moved to 4644f2bc55dSDaniel Dunbar // taking it as an input instead of hard-coding llvm::errs. 4654f2bc55dSDaniel Dunbar llvm::raw_ostream &OS = llvm::errs(); 4664f2bc55dSDaniel Dunbar 4674f2bc55dSDaniel Dunbar // Create the target instance. 4684f2bc55dSDaniel Dunbar setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); 4694f2bc55dSDaniel Dunbar if (!hasTarget()) 4704f2bc55dSDaniel Dunbar return false; 4714f2bc55dSDaniel Dunbar 4724f2bc55dSDaniel Dunbar // Inform the target of the language options. 4734f2bc55dSDaniel Dunbar // 4744f2bc55dSDaniel Dunbar // FIXME: We shouldn't need to do this, the target should be immutable once 4754f2bc55dSDaniel Dunbar // created. This complexity should be lifted elsewhere. 4764f2bc55dSDaniel Dunbar getTarget().setForcedLangOptions(getLangOpts()); 4774f2bc55dSDaniel Dunbar 4784f2bc55dSDaniel Dunbar // Validate/process some options. 4794f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose) 4804f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING 4814f2bc55dSDaniel Dunbar << " based upon " << PACKAGE_STRING 4824f2bc55dSDaniel Dunbar << " hosted on " << llvm::sys::getHostTriple() << "\n"; 4834f2bc55dSDaniel Dunbar 4844f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowTimers) 4854f2bc55dSDaniel Dunbar createFrontendTimer(); 4864f2bc55dSDaniel Dunbar 4874f2bc55dSDaniel Dunbar for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { 4884f2bc55dSDaniel Dunbar const std::string &InFile = getFrontendOpts().Inputs[i].second; 4894f2bc55dSDaniel Dunbar 4904f2bc55dSDaniel Dunbar // If we aren't using an AST file, setup the file and source managers and 4914f2bc55dSDaniel Dunbar // the preprocessor. 4924f2bc55dSDaniel Dunbar bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; 4934f2bc55dSDaniel Dunbar if (!IsAST) { 4944f2bc55dSDaniel Dunbar if (!i) { 4954f2bc55dSDaniel Dunbar // Create a file manager object to provide access to and cache the 4964f2bc55dSDaniel Dunbar // filesystem. 4974f2bc55dSDaniel Dunbar createFileManager(); 4984f2bc55dSDaniel Dunbar 4994f2bc55dSDaniel Dunbar // Create the source manager. 5004f2bc55dSDaniel Dunbar createSourceManager(); 5014f2bc55dSDaniel Dunbar } else { 5024f2bc55dSDaniel Dunbar // Reset the ID tables if we are reusing the SourceManager. 5034f2bc55dSDaniel Dunbar getSourceManager().clearIDTables(); 5044f2bc55dSDaniel Dunbar } 5054f2bc55dSDaniel Dunbar 5064f2bc55dSDaniel Dunbar // Create the preprocessor. 5074f2bc55dSDaniel Dunbar createPreprocessor(); 5084f2bc55dSDaniel Dunbar } 5094f2bc55dSDaniel Dunbar 5104f2bc55dSDaniel Dunbar if (Act.BeginSourceFile(*this, InFile, IsAST)) { 5114f2bc55dSDaniel Dunbar Act.Execute(); 5124f2bc55dSDaniel Dunbar Act.EndSourceFile(); 5134f2bc55dSDaniel Dunbar } 5144f2bc55dSDaniel Dunbar } 5154f2bc55dSDaniel Dunbar 5164f2bc55dSDaniel Dunbar if (getDiagnosticOpts().ShowCarets) 5174f2bc55dSDaniel Dunbar if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics()) 5184f2bc55dSDaniel Dunbar OS << NumDiagnostics << " diagnostic" 5194f2bc55dSDaniel Dunbar << (NumDiagnostics == 1 ? "" : "s") 5204f2bc55dSDaniel Dunbar << " generated.\n"; 5214f2bc55dSDaniel Dunbar 5224f2bc55dSDaniel Dunbar if (getFrontendOpts().ShowStats) { 5234f2bc55dSDaniel Dunbar getFileManager().PrintStats(); 5244f2bc55dSDaniel Dunbar OS << "\n"; 5254f2bc55dSDaniel Dunbar } 5264f2bc55dSDaniel Dunbar 5274f2bc55dSDaniel Dunbar // Return the appropriate status when verifying diagnostics. 5284f2bc55dSDaniel Dunbar // 5294f2bc55dSDaniel Dunbar // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need 5304f2bc55dSDaniel Dunbar // this. 5314f2bc55dSDaniel Dunbar if (getDiagnosticOpts().VerifyDiagnostics) 5324f2bc55dSDaniel Dunbar return !static_cast<VerifyDiagnosticsClient&>( 5334f2bc55dSDaniel Dunbar getDiagnosticClient()).HadErrors(); 5344f2bc55dSDaniel Dunbar 5354f2bc55dSDaniel Dunbar return !getDiagnostics().getNumErrors(); 5364f2bc55dSDaniel Dunbar } 5374f2bc55dSDaniel Dunbar 5384f2bc55dSDaniel Dunbar 539