Allow resolving headers from a PCH even after headers+PCH were moved to another path.
[clang.git] / lib / Frontend / CompilerInstance.cpp
blob412e7111e4801bc8bca1a7da227020487f885f68
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 //===----------------------------------------------------------------------===//
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Sema/Sema.h"
12 #include "clang/AST/ASTConsumer.h"
13 #include "clang/AST/ASTContext.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/Version.h"
19 #include "clang/Lex/HeaderSearch.h"
20 #include "clang/Lex/Preprocessor.h"
21 #include "clang/Lex/PTHManager.h"
22 #include "clang/Frontend/ChainedDiagnosticClient.h"
23 #include "clang/Frontend/FrontendAction.h"
24 #include "clang/Frontend/FrontendDiagnostic.h"
25 #include "clang/Frontend/TextDiagnosticPrinter.h"
26 #include "clang/Frontend/VerifyDiagnosticsClient.h"
27 #include "clang/Frontend/Utils.h"
28 #include "clang/Serialization/ASTReader.h"
29 #include "clang/Sema/CodeCompleteConsumer.h"
30 #include "llvm/LLVMContext.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/ADT/Statistic.h"
35 #include "llvm/Support/Timer.h"
36 #include "llvm/Support/Host.h"
37 #include "llvm/Support/Path.h"
38 #include "llvm/Support/Program.h"
39 #include "llvm/Support/Signals.h"
40 #include "llvm/Support/system_error.h"
41 using namespace clang;
43 CompilerInstance::CompilerInstance()
44 : Invocation(new CompilerInvocation()) {
47 CompilerInstance::~CompilerInstance() {
50 void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) {
51 LLVMContext.reset(Value);
54 void CompilerInstance::setInvocation(CompilerInvocation *Value) {
55 Invocation.reset(Value);
58 void CompilerInstance::setDiagnostics(Diagnostic *Value) {
59 Diagnostics = Value;
62 void CompilerInstance::setTarget(TargetInfo *Value) {
63 Target.reset(Value);
66 void CompilerInstance::setFileManager(FileManager *Value) {
67 FileMgr.reset(Value);
70 void CompilerInstance::setSourceManager(SourceManager *Value) {
71 SourceMgr.reset(Value);
74 void CompilerInstance::setPreprocessor(Preprocessor *Value) {
75 PP.reset(Value);
78 void CompilerInstance::setASTContext(ASTContext *Value) {
79 Context.reset(Value);
82 void CompilerInstance::setSema(Sema *S) {
83 TheSema.reset(S);
86 void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
87 Consumer.reset(Value);
90 void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
91 CompletionConsumer.reset(Value);
94 // Diagnostics
95 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
96 unsigned argc, const char* const *argv,
97 Diagnostic &Diags) {
98 std::string ErrorInfo;
99 llvm::OwningPtr<llvm::raw_ostream> OS(
100 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
101 if (!ErrorInfo.empty()) {
102 Diags.Report(diag::err_fe_unable_to_open_logfile)
103 << DiagOpts.DumpBuildInformation << ErrorInfo;
104 return;
107 (*OS) << "clang -cc1 command line arguments: ";
108 for (unsigned i = 0; i != argc; ++i)
109 (*OS) << argv[i] << ' ';
110 (*OS) << '\n';
112 // Chain in a diagnostic client which will log the diagnostics.
113 DiagnosticClient *Logger =
114 new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
115 Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
118 void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
119 DiagnosticClient *Client) {
120 Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client);
123 llvm::IntrusiveRefCntPtr<Diagnostic>
124 CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
125 int Argc, const char* const *Argv,
126 DiagnosticClient *Client) {
127 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
128 llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
130 // Create the diagnostic client for reporting errors or for
131 // implementing -verify.
132 if (Client)
133 Diags->setClient(Client);
134 else
135 Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
137 // Chain in -verify checker, if requested.
138 if (Opts.VerifyDiagnostics)
139 Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
141 if (!Opts.DumpBuildInformation.empty())
142 SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
144 // Configure our handling of diagnostics.
145 ProcessWarningOptions(*Diags, Opts);
147 return Diags;
150 // File Manager
152 void CompilerInstance::createFileManager() {
153 FileMgr.reset(new FileManager(getFileSystemOpts()));
156 // Source Manager
158 void CompilerInstance::createSourceManager(FileManager &FileMgr) {
159 SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr));
162 // Preprocessor
164 void CompilerInstance::createPreprocessor() {
165 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
166 getPreprocessorOpts(), getHeaderSearchOpts(),
167 getDependencyOutputOpts(), getTarget(),
168 getFrontendOpts(), getSourceManager(),
169 getFileManager()));
172 Preprocessor *
173 CompilerInstance::createPreprocessor(Diagnostic &Diags,
174 const LangOptions &LangInfo,
175 const PreprocessorOptions &PPOpts,
176 const HeaderSearchOptions &HSOpts,
177 const DependencyOutputOptions &DepOpts,
178 const TargetInfo &Target,
179 const FrontendOptions &FEOpts,
180 SourceManager &SourceMgr,
181 FileManager &FileMgr) {
182 // Create a PTH manager if we are using some form of a token cache.
183 PTHManager *PTHMgr = 0;
184 if (!PPOpts.TokenCache.empty())
185 PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
187 // Create the Preprocessor.
188 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
189 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
190 SourceMgr, *HeaderInfo, PTHMgr,
191 /*OwnsHeaderSearch=*/true);
193 // Note that this is different then passing PTHMgr to Preprocessor's ctor.
194 // That argument is used as the IdentifierInfoLookup argument to
195 // IdentifierTable's ctor.
196 if (PTHMgr) {
197 PTHMgr->setPreprocessor(PP);
198 PP->setPTHManager(PTHMgr);
201 if (PPOpts.DetailedRecord)
202 PP->createPreprocessingRecord();
204 InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
206 // Handle generating dependencies, if requested.
207 if (!DepOpts.OutputFile.empty())
208 AttachDependencyFileGen(*PP, DepOpts);
210 // Handle generating header include information, if requested.
211 if (DepOpts.ShowHeaderIncludes)
212 AttachHeaderIncludeGen(*PP);
213 if (!DepOpts.HeaderIncludeOutputFile.empty()) {
214 llvm::StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
215 if (OutputPath == "-")
216 OutputPath = "";
217 AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath);
220 return PP;
223 // ASTContext
225 void CompilerInstance::createASTContext() {
226 Preprocessor &PP = getPreprocessor();
227 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
228 getTarget(), PP.getIdentifierTable(),
229 PP.getSelectorTable(), PP.getBuiltinInfo(),
230 /*size_reserve=*/ 0));
233 // ExternalASTSource
235 void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
236 bool DisablePCHValidation,
237 bool DisableStatCache,
238 void *DeserializationListener){
239 llvm::OwningPtr<ExternalASTSource> Source;
240 bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
241 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
242 DisablePCHValidation,
243 DisableStatCache,
244 getPreprocessor(), getASTContext(),
245 DeserializationListener,
246 Preamble));
247 getASTContext().setExternalSource(Source);
250 ExternalASTSource *
251 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
252 const std::string &Sysroot,
253 bool DisablePCHValidation,
254 bool DisableStatCache,
255 Preprocessor &PP,
256 ASTContext &Context,
257 void *DeserializationListener,
258 bool Preamble) {
259 llvm::OwningPtr<ASTReader> Reader;
260 Reader.reset(new ASTReader(PP, &Context,
261 Sysroot.empty() ? 0 : Sysroot.c_str(),
262 DisablePCHValidation, DisableStatCache));
264 Reader->setDeserializationListener(
265 static_cast<ASTDeserializationListener *>(DeserializationListener));
266 switch (Reader->ReadAST(Path,
267 Preamble ? ASTReader::Preamble : ASTReader::PCH)) {
268 case ASTReader::Success:
269 // Set the predefines buffer as suggested by the PCH reader. Typically, the
270 // predefines buffer will be empty.
271 PP.setPredefines(Reader->getSuggestedPredefines());
272 return Reader.take();
274 case ASTReader::Failure:
275 // Unrecoverable failure: don't even try to process the input file.
276 break;
278 case ASTReader::IgnorePCH:
279 // No suitable PCH file could be found. Return an error.
280 break;
283 return 0;
286 // Code Completion
288 static bool EnableCodeCompletion(Preprocessor &PP,
289 const std::string &Filename,
290 unsigned Line,
291 unsigned Column) {
292 // Tell the source manager to chop off the given file at a specific
293 // line and column.
294 const FileEntry *Entry = PP.getFileManager().getFile(Filename);
295 if (!Entry) {
296 PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
297 << Filename;
298 return true;
301 // Truncate the named file at the given line/column.
302 PP.SetCodeCompletionPoint(Entry, Line, Column);
303 return false;
306 void CompilerInstance::createCodeCompletionConsumer() {
307 const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
308 if (!CompletionConsumer) {
309 CompletionConsumer.reset(
310 createCodeCompletionConsumer(getPreprocessor(),
311 Loc.FileName, Loc.Line, Loc.Column,
312 getFrontendOpts().ShowMacrosInCodeCompletion,
313 getFrontendOpts().ShowCodePatternsInCodeCompletion,
314 getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
315 llvm::outs()));
316 if (!CompletionConsumer)
317 return;
318 } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
319 Loc.Line, Loc.Column)) {
320 CompletionConsumer.reset();
321 return;
324 if (CompletionConsumer->isOutputBinary() &&
325 llvm::sys::Program::ChangeStdoutToBinary()) {
326 getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
327 CompletionConsumer.reset();
331 void CompilerInstance::createFrontendTimer() {
332 FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
335 CodeCompleteConsumer *
336 CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
337 const std::string &Filename,
338 unsigned Line,
339 unsigned Column,
340 bool ShowMacros,
341 bool ShowCodePatterns,
342 bool ShowGlobals,
343 llvm::raw_ostream &OS) {
344 if (EnableCodeCompletion(PP, Filename, Line, Column))
345 return 0;
347 // Set up the creation routine for code-completion.
348 return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
349 ShowGlobals, OS);
352 void CompilerInstance::createSema(bool CompleteTranslationUnit,
353 CodeCompleteConsumer *CompletionConsumer) {
354 TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
355 CompleteTranslationUnit, CompletionConsumer));
358 // Output Files
360 void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
361 assert(OutFile.OS && "Attempt to add empty stream to output list!");
362 OutputFiles.push_back(OutFile);
365 void CompilerInstance::clearOutputFiles(bool EraseFiles) {
366 for (std::list<OutputFile>::iterator
367 it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
368 delete it->OS;
369 if (!it->TempFilename.empty()) {
370 llvm::sys::Path TempPath(it->TempFilename);
371 if (EraseFiles)
372 TempPath.eraseFromDisk();
373 else {
374 std::string Error;
375 llvm::sys::Path NewOutFile(it->Filename);
376 // If '-working-directory' was passed, the output filename should be
377 // relative to that.
378 FileManager::FixupRelativePath(NewOutFile, getFileSystemOpts());
379 if (TempPath.renamePathOnDisk(NewOutFile, &Error)) {
380 getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
381 << it->TempFilename << it->Filename << Error;
382 TempPath.eraseFromDisk();
385 } else if (!it->Filename.empty() && EraseFiles)
386 llvm::sys::Path(it->Filename).eraseFromDisk();
389 OutputFiles.clear();
392 llvm::raw_fd_ostream *
393 CompilerInstance::createDefaultOutputFile(bool Binary,
394 llvm::StringRef InFile,
395 llvm::StringRef Extension) {
396 return createOutputFile(getFrontendOpts().OutputFile, Binary,
397 /*RemoveFileOnSignal=*/true, InFile, Extension);
400 llvm::raw_fd_ostream *
401 CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
402 bool Binary, bool RemoveFileOnSignal,
403 llvm::StringRef InFile,
404 llvm::StringRef Extension) {
405 std::string Error, OutputPathName, TempPathName;
406 llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
407 RemoveFileOnSignal,
408 InFile, Extension,
409 &OutputPathName,
410 &TempPathName);
411 if (!OS) {
412 getDiagnostics().Report(diag::err_fe_unable_to_open_output)
413 << OutputPath << Error;
414 return 0;
417 // Add the output file -- but don't try to remove "-", since this means we are
418 // using stdin.
419 addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
420 TempPathName, OS));
422 return OS;
425 llvm::raw_fd_ostream *
426 CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
427 std::string &Error,
428 bool Binary,
429 bool RemoveFileOnSignal,
430 llvm::StringRef InFile,
431 llvm::StringRef Extension,
432 std::string *ResultPathName,
433 std::string *TempPathName) {
434 std::string OutFile, TempFile;
435 if (!OutputPath.empty()) {
436 OutFile = OutputPath;
437 } else if (InFile == "-") {
438 OutFile = "-";
439 } else if (!Extension.empty()) {
440 llvm::sys::Path Path(InFile);
441 Path.eraseSuffix();
442 Path.appendSuffix(Extension);
443 OutFile = Path.str();
444 } else {
445 OutFile = "-";
448 if (OutFile != "-") {
449 llvm::sys::Path OutPath(OutFile);
450 // Only create the temporary if we can actually write to OutPath, otherwise
451 // we want to fail early.
452 bool Exists;
453 if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
454 (OutPath.isRegularFile() && OutPath.canWrite())) {
455 // Create a temporary file.
456 llvm::sys::Path TempPath(OutFile);
457 if (!TempPath.createTemporaryFileOnDisk())
458 TempFile = TempPath.str();
462 std::string OSFile = OutFile;
463 if (!TempFile.empty())
464 OSFile = TempFile;
466 llvm::OwningPtr<llvm::raw_fd_ostream> OS(
467 new llvm::raw_fd_ostream(OSFile.c_str(), Error,
468 (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
469 if (!Error.empty())
470 return 0;
472 // Make sure the out stream file gets removed if we crash.
473 if (RemoveFileOnSignal)
474 llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
476 if (ResultPathName)
477 *ResultPathName = OutFile;
478 if (TempPathName)
479 *TempPathName = TempFile;
481 return OS.take();
484 // Initialization Utilities
486 bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
487 return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
488 getSourceManager(), getFrontendOpts());
491 bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
492 Diagnostic &Diags,
493 FileManager &FileMgr,
494 SourceManager &SourceMgr,
495 const FrontendOptions &Opts) {
496 // Figure out where to get and map in the main file, unless it's already
497 // been created (e.g., by a precompiled preamble).
498 if (!SourceMgr.getMainFileID().isInvalid()) {
499 // Do nothing: the main file has already been set.
500 } else if (InputFile != "-") {
501 const FileEntry *File = FileMgr.getFile(InputFile);
502 if (!File) {
503 Diags.Report(diag::err_fe_error_reading) << InputFile;
504 return false;
506 SourceMgr.createMainFileID(File);
507 } else {
508 llvm::OwningPtr<llvm::MemoryBuffer> SB;
509 if (llvm::MemoryBuffer::getSTDIN(SB)) {
510 // FIXME: Give ec.message() in this diag.
511 Diags.Report(diag::err_fe_error_reading_stdin);
512 return false;
514 const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
515 SB->getBufferSize(), 0);
516 SourceMgr.createMainFileID(File);
517 SourceMgr.overrideFileContents(File, SB.take());
520 assert(!SourceMgr.getMainFileID().isInvalid() &&
521 "Couldn't establish MainFileID!");
522 return true;
525 // High-Level Operations
527 bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
528 assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
529 assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
530 assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
532 // FIXME: Take this as an argument, once all the APIs we used have moved to
533 // taking it as an input instead of hard-coding llvm::errs.
534 llvm::raw_ostream &OS = llvm::errs();
536 // Create the target instance.
537 setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
538 if (!hasTarget())
539 return false;
541 // Inform the target of the language options.
543 // FIXME: We shouldn't need to do this, the target should be immutable once
544 // created. This complexity should be lifted elsewhere.
545 getTarget().setForcedLangOptions(getLangOpts());
547 // Validate/process some options.
548 if (getHeaderSearchOpts().Verbose)
549 OS << "clang -cc1 version " CLANG_VERSION_STRING
550 << " based upon " << PACKAGE_STRING
551 << " hosted on " << llvm::sys::getHostTriple() << "\n";
553 if (getFrontendOpts().ShowTimers)
554 createFrontendTimer();
556 if (getFrontendOpts().ShowStats)
557 llvm::EnableStatistics();
559 for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
560 const std::string &InFile = getFrontendOpts().Inputs[i].second;
562 // Reset the ID tables if we are reusing the SourceManager.
563 if (hasSourceManager())
564 getSourceManager().clearIDTables();
566 if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
567 Act.Execute();
568 Act.EndSourceFile();
572 if (getDiagnosticOpts().ShowCarets) {
573 // We can have multiple diagnostics sharing one diagnostic client.
574 // Get the total number of warnings/errors from the client.
575 unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
576 unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
578 if (NumWarnings)
579 OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
580 if (NumWarnings && NumErrors)
581 OS << " and ";
582 if (NumErrors)
583 OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
584 if (NumWarnings || NumErrors)
585 OS << " generated.\n";
588 if (getFrontendOpts().ShowStats && hasFileManager()) {
589 getFileManager().PrintStats();
590 OS << "\n";
593 return !getDiagnostics().getClient()->getNumErrors();