1 //===--- CompilerInstance.cpp ---------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
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
) {
62 void CompilerInstance::setTarget(TargetInfo
*Value
) {
66 void CompilerInstance::setFileManager(FileManager
*Value
) {
70 void CompilerInstance::setSourceManager(SourceManager
*Value
) {
71 SourceMgr
.reset(Value
);
74 void CompilerInstance::setPreprocessor(Preprocessor
*Value
) {
78 void CompilerInstance::setASTContext(ASTContext
*Value
) {
82 void CompilerInstance::setSema(Sema
*S
) {
86 void CompilerInstance::setASTConsumer(ASTConsumer
*Value
) {
87 Consumer
.reset(Value
);
90 void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer
*Value
) {
91 CompletionConsumer
.reset(Value
);
95 static void SetUpBuildDumpLog(const DiagnosticOptions
&DiagOpts
,
96 unsigned argc
, const char* const *argv
,
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
;
107 (*OS
) << "clang -cc1 command line arguments: ";
108 for (unsigned i
= 0; i
!= argc
; ++i
)
109 (*OS
) << argv
[i
] << ' ';
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.
133 Diags
->setClient(Client
);
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
);
152 void CompilerInstance::createFileManager() {
153 FileMgr
.reset(new FileManager(getFileSystemOpts()));
158 void CompilerInstance::createSourceManager(FileManager
&FileMgr
) {
159 SourceMgr
.reset(new SourceManager(getDiagnostics(), FileMgr
));
164 void CompilerInstance::createPreprocessor() {
165 PP
.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
166 getPreprocessorOpts(), getHeaderSearchOpts(),
167 getDependencyOutputOpts(), getTarget(),
168 getFrontendOpts(), getSourceManager(),
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.
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
== "-")
217 AttachHeaderIncludeGen(*PP
, /*ShowAllHeaders=*/true, OutputPath
);
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));
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
,
244 getPreprocessor(), getASTContext(),
245 DeserializationListener
,
247 getASTContext().setExternalSource(Source
);
251 CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path
,
252 const std::string
&Sysroot
,
253 bool DisablePCHValidation
,
254 bool DisableStatCache
,
257 void *DeserializationListener
,
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.
278 case ASTReader::IgnorePCH
:
279 // No suitable PCH file could be found. Return an error.
288 static bool EnableCodeCompletion(Preprocessor
&PP
,
289 const std::string
&Filename
,
292 // Tell the source manager to chop off the given file at a specific
294 const FileEntry
*Entry
= PP
.getFileManager().getFile(Filename
);
296 PP
.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file
)
301 // Truncate the named file at the given line/column.
302 PP
.SetCodeCompletionPoint(Entry
, Line
, Column
);
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
,
316 if (!CompletionConsumer
)
318 } else if (EnableCodeCompletion(getPreprocessor(), Loc
.FileName
,
319 Loc
.Line
, Loc
.Column
)) {
320 CompletionConsumer
.reset();
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
,
341 bool ShowCodePatterns
,
343 llvm::raw_ostream
&OS
) {
344 if (EnableCodeCompletion(PP
, Filename
, Line
, Column
))
347 // Set up the creation routine for code-completion.
348 return new PrintingCodeCompleteConsumer(ShowMacros
, ShowCodePatterns
,
352 void CompilerInstance::createSema(bool CompleteTranslationUnit
,
353 CodeCompleteConsumer
*CompletionConsumer
) {
354 TheSema
.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
355 CompleteTranslationUnit
, CompletionConsumer
));
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
) {
369 if (!it
->TempFilename
.empty()) {
370 llvm::sys::Path
TempPath(it
->TempFilename
);
372 TempPath
.eraseFromDisk();
375 llvm::sys::Path
NewOutFile(it
->Filename
);
376 // If '-working-directory' was passed, the output filename should be
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();
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
,
412 getDiagnostics().Report(diag::err_fe_unable_to_open_output
)
413 << OutputPath
<< Error
;
417 // Add the output file -- but don't try to remove "-", since this means we are
419 addOutputFile(OutputFile((OutputPathName
!= "-") ? OutputPathName
: "",
425 llvm::raw_fd_ostream
*
426 CompilerInstance::createOutputFile(llvm::StringRef OutputPath
,
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
== "-") {
439 } else if (!Extension
.empty()) {
440 llvm::sys::Path
Path(InFile
);
442 Path
.appendSuffix(Extension
);
443 OutFile
= Path
.str();
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.
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())
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)));
472 // Make sure the out stream file gets removed if we crash.
473 if (RemoveFileOnSignal
)
474 llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile
));
477 *ResultPathName
= OutFile
;
479 *TempPathName
= TempFile
;
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
,
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
);
503 Diags
.Report(diag::err_fe_error_reading
) << InputFile
;
506 SourceMgr
.createMainFileID(File
);
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
);
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!");
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()));
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
)) {
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();
579 OS
<< NumWarnings
<< " warning" << (NumWarnings
== 1 ? "" : "s");
580 if (NumWarnings
&& NumErrors
)
583 OS
<< NumErrors
<< " error" << (NumErrors
== 1 ? "" : "s");
584 if (NumWarnings
|| NumErrors
)
585 OS
<< " generated.\n";
588 if (getFrontendOpts().ShowStats
&& hasFileManager()) {
589 getFileManager().PrintStats();
593 return !getDiagnostics().getClient()->getNumErrors();