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/Lex/HeaderSearch.h" 18 #include "clang/Lex/Preprocessor.h" 19 #include "clang/Lex/PTHManager.h" 20 #include "clang/Frontend/ChainedDiagnosticClient.h" 21 #include "clang/Frontend/PCHReader.h" 22 #include "clang/Frontend/FrontendDiagnostic.h" 23 #include "clang/Frontend/TextDiagnosticPrinter.h" 24 #include "clang/Frontend/VerifyDiagnosticsClient.h" 25 #include "clang/Frontend/Utils.h" 26 #include "clang/Sema/CodeCompleteConsumer.h" 27 #include "llvm/LLVMContext.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include "llvm/System/Path.h" 30 using namespace clang; 31 32 CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, 33 bool _OwnsLLVMContext) 34 : LLVMContext(_LLVMContext), 35 OwnsLLVMContext(_OwnsLLVMContext) { 36 } 37 38 CompilerInstance::~CompilerInstance() { 39 if (OwnsLLVMContext) 40 delete LLVMContext; 41 } 42 43 void CompilerInstance::setDiagnostics(Diagnostic *Value) { 44 Diagnostics.reset(Value); 45 } 46 47 void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { 48 DiagClient.reset(Value); 49 } 50 51 void CompilerInstance::setTarget(TargetInfo *Value) { 52 Target.reset(Value); 53 } 54 55 void CompilerInstance::setFileManager(FileManager *Value) { 56 FileMgr.reset(Value); 57 } 58 59 void CompilerInstance::setSourceManager(SourceManager *Value) { 60 SourceMgr.reset(Value); 61 } 62 63 void CompilerInstance::setPreprocessor(Preprocessor *Value) { 64 PP.reset(Value); 65 } 66 67 void CompilerInstance::setASTContext(ASTContext *Value) { 68 Context.reset(Value); 69 } 70 71 void CompilerInstance::setASTConsumer(ASTConsumer *Value) { 72 Consumer.reset(Value); 73 } 74 75 void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { 76 CompletionConsumer.reset(Value); 77 } 78 79 // Diagnostics 80 81 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, 82 unsigned argc, char **argv, 83 llvm::OwningPtr<DiagnosticClient> &DiagClient) { 84 std::string ErrorInfo; 85 llvm::raw_ostream *OS = 86 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo); 87 if (!ErrorInfo.empty()) { 88 // FIXME: Do not fail like this. 89 llvm::errs() << "error opening -dump-build-information file '" 90 << DiagOpts.DumpBuildInformation << "', option ignored!\n"; 91 delete OS; 92 return; 93 } 94 95 (*OS) << "clang-cc command line arguments: "; 96 for (unsigned i = 0; i != argc; ++i) 97 (*OS) << argv[i] << ' '; 98 (*OS) << '\n'; 99 100 // Chain in a diagnostic client which will log the diagnostics. 101 DiagnosticClient *Logger = 102 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true); 103 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger)); 104 } 105 106 void CompilerInstance::createDiagnostics(int Argc, char **Argv) { 107 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); 108 109 if (Diagnostics) 110 DiagClient.reset(Diagnostics->getClient()); 111 } 112 113 Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, 114 int Argc, char **Argv) { 115 // Create the diagnostic client for reporting errors or for 116 // implementing -verify. 117 llvm::OwningPtr<DiagnosticClient> DiagClient( 118 new TextDiagnosticPrinter(llvm::errs(), Opts)); 119 120 // Chain in -verify checker, if requested. 121 if (Opts.VerifyDiagnostics) 122 DiagClient.reset(new VerifyDiagnosticsClient(DiagClient.take())); 123 124 if (!Opts.DumpBuildInformation.empty()) 125 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient); 126 127 // Configure our handling of diagnostics. 128 Diagnostic *Diags = new Diagnostic(DiagClient.take()); 129 if (ProcessWarningOptions(*Diags, Opts)) 130 return 0; 131 132 return Diags; 133 } 134 135 // File Manager 136 137 void CompilerInstance::createFileManager() { 138 FileMgr.reset(new FileManager()); 139 } 140 141 // Source Manager 142 143 void CompilerInstance::createSourceManager() { 144 SourceMgr.reset(new SourceManager()); 145 } 146 147 // Preprocessor 148 149 void CompilerInstance::createPreprocessor() { 150 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), 151 getPreprocessorOpts(), getHeaderSearchOpts(), 152 getDependencyOutputOpts(), getTarget(), 153 getSourceManager(), getFileManager())); 154 } 155 156 Preprocessor * 157 CompilerInstance::createPreprocessor(Diagnostic &Diags, 158 const LangOptions &LangInfo, 159 const PreprocessorOptions &PPOpts, 160 const HeaderSearchOptions &HSOpts, 161 const DependencyOutputOptions &DepOpts, 162 const TargetInfo &Target, 163 SourceManager &SourceMgr, 164 FileManager &FileMgr) { 165 // Create a PTH manager if we are using some form of a token cache. 166 PTHManager *PTHMgr = 0; 167 if (!PPOpts.getTokenCache().empty()) 168 PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags); 169 170 // FIXME: Don't fail like this. 171 if (Diags.hasErrorOccurred()) 172 exit(1); 173 174 // Create the Preprocessor. 175 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr); 176 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target, 177 SourceMgr, *HeaderInfo, PTHMgr, 178 /*OwnsHeaderSearch=*/true); 179 180 // Note that this is different then passing PTHMgr to Preprocessor's ctor. 181 // That argument is used as the IdentifierInfoLookup argument to 182 // IdentifierTable's ctor. 183 if (PTHMgr) { 184 PTHMgr->setPreprocessor(PP); 185 PP->setPTHManager(PTHMgr); 186 } 187 188 InitializePreprocessor(*PP, PPOpts, HSOpts); 189 190 // Handle generating dependencies, if requested. 191 if (!DepOpts.OutputFile.empty()) 192 AttachDependencyFileGen(*PP, DepOpts); 193 194 return PP; 195 } 196 197 // ASTContext 198 199 void CompilerInstance::createASTContext() { 200 Preprocessor &PP = getPreprocessor(); 201 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), 202 getTarget(), PP.getIdentifierTable(), 203 PP.getSelectorTable(), PP.getBuiltinInfo(), 204 /*FreeMemory=*/ !getFrontendOpts().DisableFree, 205 /*size_reserve=*/ 0)); 206 } 207 208 // ExternalASTSource 209 210 void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) { 211 llvm::OwningPtr<ExternalASTSource> Source; 212 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, 213 getPreprocessor(), getASTContext())); 214 getASTContext().setExternalSource(Source); 215 } 216 217 ExternalASTSource * 218 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, 219 const std::string &Sysroot, 220 Preprocessor &PP, 221 ASTContext &Context) { 222 llvm::OwningPtr<PCHReader> Reader; 223 Reader.reset(new PCHReader(PP, &Context, 224 Sysroot.empty() ? 0 : Sysroot.c_str())); 225 226 switch (Reader->ReadPCH(Path)) { 227 case PCHReader::Success: 228 // Set the predefines buffer as suggested by the PCH reader. Typically, the 229 // predefines buffer will be empty. 230 PP.setPredefines(Reader->getSuggestedPredefines()); 231 return Reader.take(); 232 233 case PCHReader::Failure: 234 // Unrecoverable failure: don't even try to process the input file. 235 break; 236 237 case PCHReader::IgnorePCH: 238 // No suitable PCH file could be found. Return an error. 239 break; 240 } 241 242 return 0; 243 } 244 245 // Code Completion 246 247 void CompilerInstance::createCodeCompletionConsumer() { 248 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt; 249 CompletionConsumer.reset( 250 createCodeCompletionConsumer(getPreprocessor(), 251 Loc.FileName, Loc.Line, Loc.Column, 252 getFrontendOpts().DebugCodeCompletionPrinter, 253 getFrontendOpts().ShowMacrosInCodeCompletion, 254 llvm::outs())); 255 } 256 257 CodeCompleteConsumer * 258 CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, 259 const std::string &Filename, 260 unsigned Line, 261 unsigned Column, 262 bool UseDebugPrinter, 263 bool ShowMacros, 264 llvm::raw_ostream &OS) { 265 // Tell the source manager to chop off the given file at a specific 266 // line and column. 267 const FileEntry *Entry = PP.getFileManager().getFile(Filename); 268 if (!Entry) { 269 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file) 270 << Filename; 271 return 0; 272 } 273 274 // Truncate the named file at the given line/column. 275 PP.getSourceManager().truncateFileAt(Entry, Line, Column); 276 277 // Set up the creation routine for code-completion. 278 if (UseDebugPrinter) 279 return new PrintingCodeCompleteConsumer(ShowMacros, OS); 280 else 281 return new CIndexCodeCompleteConsumer(ShowMacros, OS); 282 } 283 284 // Output Files 285 286 void CompilerInstance::addOutputFile(llvm::StringRef Path, 287 llvm::raw_ostream *OS) { 288 assert(OS && "Attempt to add empty stream to output list!"); 289 OutputFiles.push_back(std::make_pair(Path, OS)); 290 } 291 292 void CompilerInstance::ClearOutputFiles(bool EraseFiles) { 293 for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator 294 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { 295 delete it->second; 296 if (EraseFiles && !it->first.empty()) 297 llvm::sys::Path(it->first).eraseFromDisk(); 298 } 299 OutputFiles.clear(); 300 } 301 302 llvm::raw_fd_ostream * 303 CompilerInstance::createDefaultOutputFile(bool Binary, 304 llvm::StringRef InFile, 305 llvm::StringRef Extension) { 306 return createOutputFile(getFrontendOpts().OutputFile, Binary, 307 InFile, Extension); 308 } 309 310 llvm::raw_fd_ostream * 311 CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 312 bool Binary, 313 llvm::StringRef InFile, 314 llvm::StringRef Extension) { 315 std::string Error, OutputPathName; 316 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, 317 InFile, Extension, 318 &OutputPathName); 319 if (!OS) { 320 // FIXME: Don't fail this way. 321 llvm::errs() << "ERROR: " << Error << "\n"; 322 ::exit(1); 323 } 324 325 // Add the output file -- but don't try to remove "-", since this means we are 326 // using stdin. 327 addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS); 328 329 return OS; 330 } 331 332 llvm::raw_fd_ostream * 333 CompilerInstance::createOutputFile(llvm::StringRef OutputPath, 334 std::string &Error, 335 bool Binary, 336 llvm::StringRef InFile, 337 llvm::StringRef Extension, 338 std::string *ResultPathName) { 339 std::string OutFile; 340 if (!OutputPath.empty()) { 341 OutFile = OutputPath; 342 } else if (InFile == "-") { 343 OutFile = "-"; 344 } else if (!Extension.empty()) { 345 llvm::sys::Path Path(InFile); 346 Path.eraseSuffix(); 347 Path.appendSuffix(Extension); 348 OutFile = Path.str(); 349 } else { 350 OutFile = "-"; 351 } 352 353 llvm::raw_fd_ostream *OS = 354 new llvm::raw_fd_ostream(OutFile.c_str(), Error, 355 (Binary ? llvm::raw_fd_ostream::F_Binary : 0)); 356 if (!OS) 357 return 0; 358 359 if (ResultPathName) 360 *ResultPathName = OutFile; 361 362 return OS; 363 } 364