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/ASTContext.h" 12 #include "clang/Basic/Diagnostic.h" 13 #include "clang/Basic/FileManager.h" 14 #include "clang/Basic/SourceManager.h" 15 #include "clang/Basic/TargetInfo.h" 16 #include "clang/Lex/HeaderSearch.h" 17 #include "clang/Lex/Preprocessor.h" 18 #include "clang/Lex/PTHManager.h" 19 #include "clang/Frontend/ChainedDiagnosticClient.h" 20 #include "clang/Frontend/PCHReader.h" 21 #include "clang/Frontend/FrontendDiagnostic.h" 22 #include "clang/Frontend/TextDiagnosticBuffer.h" 23 #include "clang/Frontend/TextDiagnosticPrinter.h" 24 #include "clang/Frontend/Utils.h" 25 #include "clang/Sema/CodeCompleteConsumer.h" 26 #include "llvm/LLVMContext.h" 27 #include "llvm/Support/raw_ostream.h" 28 using namespace clang; 29 30 CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, 31 bool _OwnsLLVMContext) 32 : LLVMContext(_LLVMContext), 33 OwnsLLVMContext(_OwnsLLVMContext) { 34 } 35 36 CompilerInstance::~CompilerInstance() { 37 if (OwnsLLVMContext) 38 delete LLVMContext; 39 } 40 41 // Diagnostics 42 43 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 44 unsigned argc, char **argv, 45 llvm::OwningPtr<DiagnosticClient> &DiagClient) { 46 std::string ErrorInfo; 47 llvm::raw_ostream *OS = 48 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo); 49 if (!ErrorInfo.empty()) { 50 // FIXME: Do not fail like this. 51 llvm::errs() << "error opening -dump-build-information file '" 52 << DiagOpts.DumpBuildInformation << "', option ignored!\n"; 53 delete OS; 54 return; 55 } 56 57 (*OS) << "clang-cc command line arguments: "; 58 for (unsigned i = 0; i != argc; ++i) 59 (*OS) << argv[i] << ' '; 60 (*OS) << '\n'; 61 62 // Chain in a diagnostic client which will log the diagnostics. 63 DiagnosticClient *Logger = 64 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true); 65 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger)); 66 } 67 68 void CompilerInstance::createDiagnostics(int Argc, char **Argv) { 69 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); 70 71 if (Diagnostics) 72 DiagClient.reset(Diagnostics->getClient()); 73 } 74 75 Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 76 int Argc, char **Argv) { 77 // Create the diagnostic client for reporting errors or for 78 // implementing -verify. 79 llvm::OwningPtr<DiagnosticClient> DiagClient; 80 if (Opts.VerifyDiagnostics) { 81 // When checking diagnostics, just buffer them up. 82 DiagClient.reset(new TextDiagnosticBuffer()); 83 } else { 84 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); 85 } 86 87 if (!Opts.DumpBuildInformation.empty()) 88 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient); 89 90 // Configure our handling of diagnostics. 91 Diagnostic *Diags = new Diagnostic(DiagClient.take()); 92 if (ProcessWarningOptions(*Diags, Opts)) 93 return 0; 94 95 return Diags; 96 } 97 98 // File Manager 99 100 void CompilerInstance::createFileManager() { 101 FileMgr.reset(new FileManager()); 102 } 103 104 // Source Manager 105 106 void CompilerInstance::createSourceManager() { 107 SourceMgr.reset(new SourceManager()); 108 } 109 110 // Preprocessor 111 112 void CompilerInstance::createPreprocessor() { 113 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 114 getPreprocessorOpts(), getHeaderSearchOpts(), 115 getDependencyOutputOpts(), getTarget(), 116 getSourceManager(), getFileManager())); 117 } 118 119 Preprocessor * 120 CompilerInstance::createPreprocessor(Diagnostic &Diags, 121 const LangOptions &LangInfo, 122 const PreprocessorOptions &PPOpts, 123 const HeaderSearchOptions &HSOpts, 124 const DependencyOutputOptions &DepOpts, 125 const TargetInfo &Target, 126 SourceManager &SourceMgr, 127 FileManager &FileMgr) { 128 // Create a PTH manager if we are using some form of a token cache. 129 PTHManager *PTHMgr = 0; 130 if (!PPOpts.getTokenCache().empty()) 131 PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags); 132 133 // FIXME: Don't fail like this. 134 if (Diags.hasErrorOccurred()) 135 exit(1); 136 137 // Create the Preprocessor. 138 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 139 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 140 SourceMgr, *HeaderInfo, PTHMgr, 141 /*OwnsHeaderSearch=*/true); 142 143 // Note that this is different then passing PTHMgr to Preprocessor's ctor. 144 // That argument is used as the IdentifierInfoLookup argument to 145 // IdentifierTable's ctor. 146 if (PTHMgr) { 147 PTHMgr->setPreprocessor(PP); 148 PP->setPTHManager(PTHMgr); 149 } 150 151 InitializePreprocessor(*PP, PPOpts, HSOpts); 152 153 // Handle generating dependencies, if requested. 154 if (!DepOpts.OutputFile.empty()) 155 AttachDependencyFileGen(*PP, DepOpts); 156 157 return PP; 158 } 159 160 // ASTContext 161 162 void CompilerInstance::createASTContext() { 163 Preprocessor &PP = getPreprocessor(); 164 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), 165 getTarget(), PP.getIdentifierTable(), 166 PP.getSelectorTable(), PP.getBuiltinInfo(), 167 /*FreeMemory=*/ !getFrontendOpts().DisableFree, 168 /*size_reserve=*/ 0)); 169 } 170 171 // ExternalASTSource 172 173 void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { 174 llvm::OwningPtr<ExternalASTSource> Source; 175 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 176 getPreprocessor(), getASTContext())); 177 getASTContext().setExternalSource(Source); 178 } 179 180 ExternalASTSource * 181 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, 182 const std::string &Sysroot, 183 Preprocessor &PP, 184 ASTContext &Context) { 185 llvm::OwningPtr<PCHReader> Reader; 186 Reader.reset(new PCHReader(PP, &Context, 187 Sysroot.empty() ? 0 : Sysroot.c_str())); 188 189 switch (Reader->ReadPCH(Path)) { 190 case PCHReader::Success: 191 // Set the predefines buffer as suggested by the PCH reader. Typically, the 192 // predefines buffer will be empty. 193 PP.setPredefines(Reader->getSuggestedPredefines()); 194 return Reader.take(); 195 196 case PCHReader::Failure: 197 // Unrecoverable failure: don't even try to process the input file. 198 break; 199 200 case PCHReader::IgnorePCH: 201 // No suitable PCH file could be found. Return an error. 202 break; 203 } 204 205 return 0; 206 } 207 208 // Code Completion 209 210 void CompilerInstance::createCodeCompletionConsumer() { 211 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 212 CompletionConsumer.reset( 213 createCodeCompletionConsumer(getPreprocessor(), 214 Loc.FileName, Loc.Line, Loc.Column, 215 getFrontendOpts().DebugCodeCompletionPrinter, 216 getFrontendOpts().ShowMacrosInCodeCompletion, 217 llvm::outs())); 218 } 219 220 CodeCompleteConsumer * 221 CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 222 const std::string &Filename, 223 unsigned Line, 224 unsigned Column, 225 bool UseDebugPrinter, 226 bool ShowMacros, 227 llvm::raw_ostream &OS) { 228 // Tell the source manager to chop off the given file at a specific 229 // line and column. 230 const FileEntry *Entry = PP.getFileManager().getFile(Filename); 231 if (!Entry) { 232 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 233 << Filename; 234 return 0; 235 } 236 237 // Truncate the named file at the given line/column. 238 PP.getSourceManager().truncateFileAt(Entry, Line, Column); 239 240 // Set up the creation routine for code-completion. 241 if (UseDebugPrinter) 242 return new PrintingCodeCompleteConsumer(ShowMacros, OS); 243 else 244 return new CIndexCodeCompleteConsumer(ShowMacros, OS); 245 } 246