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/Basic/Diagnostic.h" 12 #include "clang/Basic/FileManager.h" 13 #include "clang/Basic/SourceManager.h" 14 #include "clang/Basic/TargetInfo.h" 15 #include "clang/Lex/HeaderSearch.h" 16 #include "clang/Lex/Preprocessor.h" 17 #include "clang/Lex/PTHManager.h" 18 #include "clang/Frontend/ChainedDiagnosticClient.h" 19 #include "clang/Frontend/TextDiagnosticBuffer.h" 20 #include "clang/Frontend/TextDiagnosticPrinter.h" 21 #include "clang/Frontend/Utils.h" 22 #include "llvm/LLVMContext.h" 23 #include "llvm/Support/raw_ostream.h" 24 using namespace clang; 25 26 CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, 27 bool _OwnsLLVMContext) 28 : LLVMContext(_LLVMContext), 29 OwnsLLVMContext(_OwnsLLVMContext) { 30 } 31 32 CompilerInstance::~CompilerInstance() { 33 if (OwnsLLVMContext) 34 delete LLVMContext; 35 } 36 37 // Diagnostics 38 39 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 40 unsigned argc, char **argv, 41 llvm::OwningPtr<DiagnosticClient> &DiagClient) { 42 std::string ErrorInfo; 43 llvm::raw_ostream *OS = 44 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo); 45 if (!ErrorInfo.empty()) { 46 // FIXME: Do not fail like this. 47 llvm::errs() << "error opening -dump-build-information file '" 48 << DiagOpts.DumpBuildInformation << "', option ignored!\n"; 49 delete OS; 50 return; 51 } 52 53 (*OS) << "clang-cc command line arguments: "; 54 for (unsigned i = 0; i != argc; ++i) 55 (*OS) << argv[i] << ' '; 56 (*OS) << '\n'; 57 58 // Chain in a diagnostic client which will log the diagnostics. 59 DiagnosticClient *Logger = 60 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true); 61 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger)); 62 } 63 64 void CompilerInstance::createDiagnostics(int Argc, char **Argv) { 65 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); 66 67 if (Diagnostics) 68 DiagClient.reset(Diagnostics->getClient()); 69 } 70 71 Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 72 int Argc, char **Argv) { 73 // Create the diagnostic client for reporting errors or for 74 // implementing -verify. 75 llvm::OwningPtr<DiagnosticClient> DiagClient; 76 if (Opts.VerifyDiagnostics) { 77 // When checking diagnostics, just buffer them up. 78 DiagClient.reset(new TextDiagnosticBuffer()); 79 } else { 80 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 81 } 82 83 if (!Opts.DumpBuildInformation.empty()) 84 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient); 85 86 // Configure our handling of diagnostics. 87 Diagnostic *Diags = new Diagnostic(DiagClient.take()); 88 if (ProcessWarningOptions(*Diags, Opts)) 89 return 0; 90 91 return Diags; 92 } 93 94 // File Manager 95 96 void CompilerInstance::createFileManager() { 97 FileMgr.reset(new FileManager()); 98 } 99 100 // Source Manager 101 102 void CompilerInstance::createSourceManager() { 103 SourceMgr.reset(new SourceManager()); 104 } 105 106 // Preprocessor 107 108 void CompilerInstance::createPreprocessor() { 109 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 110 getPreprocessorOpts(), getHeaderSearchOpts(), 111 getDependencyOutputOpts(), getTarget(), 112 getSourceManager(), getFileManager())); 113 } 114 115 Preprocessor * 116 CompilerInstance::createPreprocessor(Diagnostic &Diags, 117 const LangOptions &LangInfo, 118 const PreprocessorOptions &PPOpts, 119 const HeaderSearchOptions &HSOpts, 120 const DependencyOutputOptions &DepOpts, 121 const TargetInfo &Target, 122 SourceManager &SourceMgr, 123 FileManager &FileMgr) { 124 // Create a PTH manager if we are using some form of a token cache. 125 PTHManager *PTHMgr = 0; 126 if (!PPOpts.getTokenCache().empty()) 127 PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags); 128 129 // FIXME: Don't fail like this. 130 if (Diags.hasErrorOccurred()) 131 exit(1); 132 133 // Create the Preprocessor. 134 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 135 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 136 SourceMgr, *HeaderInfo, PTHMgr, 137 /*OwnsHeaderSearch=*/true); 138 139 // Note that this is different then passing PTHMgr to Preprocessor's ctor. 140 // That argument is used as the IdentifierInfoLookup argument to 141 // IdentifierTable's ctor. 142 if (PTHMgr) { 143 PTHMgr->setPreprocessor(PP); 144 PP->setPTHManager(PTHMgr); 145 } 146 147 InitializePreprocessor(*PP, PPOpts, HSOpts); 148 149 // Handle generating dependencies, if requested. 150 if (!DepOpts.OutputFile.empty()) 151 AttachDependencyFileGen(*PP, DepOpts); 152 153 return PP; 154 } 155