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