diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp | 221 |
1 files changed, 125 insertions, 96 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp index ce0b072..fd593de 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp @@ -27,14 +27,16 @@ #include "clang/Frontend/Utils.h" #include "clang/Serialization/ASTReader.h" #include "clang/Sema/CodeCompleteConsumer.h" -#include "llvm/LLVMContext.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Timer.h" -#include "llvm/System/Host.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" using namespace clang; CompilerInstance::CompilerInstance() @@ -44,10 +46,6 @@ CompilerInstance::CompilerInstance() CompilerInstance::~CompilerInstance() { } -void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) { - LLVMContext.reset(Value); -} - void CompilerInstance::setInvocation(CompilerInvocation *Value) { Invocation.reset(Value); } @@ -89,26 +87,8 @@ void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { } // Diagnostics -namespace { - class BinaryDiagnosticSerializer : public DiagnosticClient { - llvm::raw_ostream &OS; - SourceManager *SourceMgr; - public: - explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS) - : OS(OS), SourceMgr(0) { } - - virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, - const DiagnosticInfo &Info); - }; -} - -void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel, - const DiagnosticInfo &Info) { - StoredDiagnostic(DiagLevel, Info).Serialize(OS); -} - static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, - unsigned argc, char **argv, + unsigned argc, const char* const *argv, Diagnostic &Diags) { std::string ErrorInfo; llvm::OwningPtr<llvm::raw_ostream> OS( @@ -130,33 +110,24 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger)); } -void CompilerInstance::createDiagnostics(int Argc, char **Argv) { - Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv); +void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, + DiagnosticClient *Client) { + Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client); } llvm::IntrusiveRefCntPtr<Diagnostic> CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, - int Argc, char **Argv) { - llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic()); + int Argc, const char* const *Argv, + DiagnosticClient *Client) { + llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); + llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID)); // Create the diagnostic client for reporting errors or for // implementing -verify. - llvm::OwningPtr<DiagnosticClient> DiagClient; - if (Opts.BinaryOutput) { - if (llvm::sys::Program::ChangeStderrToBinary()) { - // We weren't able to set standard error to binary, which is a - // bit of a problem. So, just create a text diagnostic printer - // to complain about this problem, and pretend that the user - // didn't try to use binary output. - Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); - Diags->Report(diag::err_fe_stderr_binary); - return Diags; - } else { - Diags->setClient(new BinaryDiagnosticSerializer(llvm::errs())); - } - } else { + if (Client) + Diags->setClient(Client); + else Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); - } // Chain in -verify checker, if requested. if (Opts.VerifyDiagnostics) @@ -174,13 +145,13 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // File Manager void CompilerInstance::createFileManager() { - FileMgr.reset(new FileManager()); + FileMgr.reset(new FileManager(getFileSystemOpts())); } // Source Manager -void CompilerInstance::createSourceManager() { - SourceMgr.reset(new SourceManager(getDiagnostics())); +void CompilerInstance::createSourceManager(FileManager &FileMgr) { + SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr)); } // Preprocessor @@ -231,6 +202,16 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, if (!DepOpts.OutputFile.empty()) AttachDependencyFileGen(*PP, DepOpts); + // Handle generating header include information, if requested. + if (DepOpts.ShowHeaderIncludes) + AttachHeaderIncludeGen(*PP); + if (!DepOpts.HeaderIncludeOutputFile.empty()) { + llvm::StringRef OutputPath = DepOpts.HeaderIncludeOutputFile; + if (OutputPath == "-") + OutputPath = ""; + AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath); + } + return PP; } @@ -248,12 +229,16 @@ void CompilerInstance::createASTContext() { void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, bool DisablePCHValidation, + bool DisableStatCache, void *DeserializationListener){ llvm::OwningPtr<ExternalASTSource> Source; + bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, - DisablePCHValidation, + DisablePCHValidation, + DisableStatCache, getPreprocessor(), getASTContext(), - DeserializationListener)); + DeserializationListener, + Preamble)); getASTContext().setExternalSource(Source); } @@ -261,17 +246,20 @@ ExternalASTSource * CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, + bool DisableStatCache, Preprocessor &PP, ASTContext &Context, - void *DeserializationListener) { + void *DeserializationListener, + bool Preamble) { llvm::OwningPtr<ASTReader> Reader; Reader.reset(new ASTReader(PP, &Context, Sysroot.empty() ? 0 : Sysroot.c_str(), - DisablePCHValidation)); + DisablePCHValidation, DisableStatCache)); Reader->setDeserializationListener( static_cast<ASTDeserializationListener *>(DeserializationListener)); - switch (Reader->ReadAST(Path)) { + switch (Reader->ReadAST(Path, + Preamble ? ASTReader::Preamble : ASTReader::PCH)) { case ASTReader::Success: // Set the predefines buffer as suggested by the PCH reader. Typically, the // predefines buffer will be empty. @@ -316,7 +304,6 @@ void CompilerInstance::createCodeCompletionConsumer() { CompletionConsumer.reset( createCodeCompletionConsumer(getPreprocessor(), Loc.FileName, Loc.Line, Loc.Column, - getFrontendOpts().DebugCodeCompletionPrinter, getFrontendOpts().ShowMacrosInCodeCompletion, getFrontendOpts().ShowCodePatternsInCodeCompletion, getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, @@ -345,7 +332,6 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, - bool UseDebugPrinter, bool ShowMacros, bool ShowCodePatterns, bool ShowGlobals, @@ -354,11 +340,7 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, return 0; // Set up the creation routine for code-completion. - if (UseDebugPrinter) - return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, - ShowGlobals, OS); - else - return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, + return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, ShowGlobals, OS); } @@ -370,18 +352,34 @@ void CompilerInstance::createSema(bool CompleteTranslationUnit, // Output Files -void CompilerInstance::addOutputFile(llvm::StringRef Path, - llvm::raw_ostream *OS) { - assert(OS && "Attempt to add empty stream to output list!"); - OutputFiles.push_back(std::make_pair(Path, OS)); +void CompilerInstance::addOutputFile(const OutputFile &OutFile) { + assert(OutFile.OS && "Attempt to add empty stream to output list!"); + OutputFiles.push_back(OutFile); } void CompilerInstance::clearOutputFiles(bool EraseFiles) { - for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator + for (std::list<OutputFile>::iterator it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) { - delete it->second; - if (EraseFiles && !it->first.empty()) - llvm::sys::Path(it->first).eraseFromDisk(); + delete it->OS; + if (!it->TempFilename.empty()) { + llvm::sys::Path TempPath(it->TempFilename); + if (EraseFiles) + TempPath.eraseFromDisk(); + else { + std::string Error; + llvm::sys::Path NewOutFile(it->Filename); + // If '-working-directory' was passed, the output filename should be + // relative to that. + FileManager::FixupRelativePath(NewOutFile, getFileSystemOpts()); + if (TempPath.renamePathOnDisk(NewOutFile, &Error)) { + getDiagnostics().Report(diag::err_fe_unable_to_rename_temp) + << it->TempFilename << it->Filename << Error; + TempPath.eraseFromDisk(); + } + } + } else if (!it->Filename.empty() && EraseFiles) + llvm::sys::Path(it->Filename).eraseFromDisk(); + } OutputFiles.clear(); } @@ -391,18 +389,20 @@ CompilerInstance::createDefaultOutputFile(bool Binary, llvm::StringRef InFile, llvm::StringRef Extension) { return createOutputFile(getFrontendOpts().OutputFile, Binary, - InFile, Extension); + /*RemoveFileOnSignal=*/true, InFile, Extension); } llvm::raw_fd_ostream * CompilerInstance::createOutputFile(llvm::StringRef OutputPath, - bool Binary, + bool Binary, bool RemoveFileOnSignal, llvm::StringRef InFile, llvm::StringRef Extension) { - std::string Error, OutputPathName; + std::string Error, OutputPathName, TempPathName; llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary, + RemoveFileOnSignal, InFile, Extension, - &OutputPathName); + &OutputPathName, + &TempPathName); if (!OS) { getDiagnostics().Report(diag::err_fe_unable_to_open_output) << OutputPath << Error; @@ -411,7 +411,8 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath, // Add the output file -- but don't try to remove "-", since this means we are // using stdin. - addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS); + addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "", + TempPathName, OS)); return OS; } @@ -420,10 +421,12 @@ llvm::raw_fd_ostream * CompilerInstance::createOutputFile(llvm::StringRef OutputPath, std::string &Error, bool Binary, + bool RemoveFileOnSignal, llvm::StringRef InFile, llvm::StringRef Extension, - std::string *ResultPathName) { - std::string OutFile; + std::string *ResultPathName, + std::string *TempPathName) { + std::string OutFile, TempFile; if (!OutputPath.empty()) { OutFile = OutputPath; } else if (InFile == "-") { @@ -436,15 +439,39 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath, } else { OutFile = "-"; } + + if (OutFile != "-") { + llvm::sys::Path OutPath(OutFile); + // Only create the temporary if we can actually write to OutPath, otherwise + // we want to fail early. + bool Exists; + if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) || + (OutPath.isRegularFile() && OutPath.canWrite())) { + // Create a temporary file. + llvm::sys::Path TempPath(OutFile); + if (!TempPath.createTemporaryFileOnDisk()) + TempFile = TempPath.str(); + } + } + + std::string OSFile = OutFile; + if (!TempFile.empty()) + OSFile = TempFile; llvm::OwningPtr<llvm::raw_fd_ostream> OS( - new llvm::raw_fd_ostream(OutFile.c_str(), Error, + new llvm::raw_fd_ostream(OSFile.c_str(), Error, (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); if (!Error.empty()) return 0; + // Make sure the out stream file gets removed if we crash. + if (RemoveFileOnSignal) + llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); + if (ResultPathName) *ResultPathName = OutFile; + if (TempPathName) + *TempPathName = TempFile; return OS.take(); } @@ -461,23 +488,32 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, FileManager &FileMgr, SourceManager &SourceMgr, const FrontendOptions &Opts) { - // Figure out where to get and map in the main file. - if (InputFile != "-") { + // Figure out where to get and map in the main file, unless it's already + // been created (e.g., by a precompiled preamble). + if (!SourceMgr.getMainFileID().isInvalid()) { + // Do nothing: the main file has already been set. + } else if (InputFile != "-") { const FileEntry *File = FileMgr.getFile(InputFile); - if (File) SourceMgr.createMainFileID(File); - if (SourceMgr.getMainFileID().isInvalid()) { + if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; } + SourceMgr.createMainFileID(File); } else { - llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN(); - if (SB) SourceMgr.createMainFileIDForMemBuffer(SB); - if (SourceMgr.getMainFileID().isInvalid()) { + llvm::OwningPtr<llvm::MemoryBuffer> SB; + if (llvm::MemoryBuffer::getSTDIN(SB)) { + // FIXME: Give ec.message() in this diag. Diags.Report(diag::err_fe_error_reading_stdin); return false; } + const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), + SB->getBufferSize(), 0); + SourceMgr.createMainFileID(File); + SourceMgr.overrideFileContents(File, SB.take()); } + assert(!SourceMgr.getMainFileID().isInvalid() && + "Couldn't establish MainFileID!"); return true; } @@ -529,9 +565,10 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { } if (getDiagnosticOpts().ShowCarets) { - unsigned NumWarnings = getDiagnostics().getNumWarnings(); - unsigned NumErrors = getDiagnostics().getNumErrors() - - getDiagnostics().getNumErrorsSuppressed(); + // We can have multiple diagnostics sharing one diagnostic client. + // Get the total number of warnings/errors from the client. + unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings(); + unsigned NumErrors = getDiagnostics().getClient()->getNumErrors(); if (NumWarnings) OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); @@ -548,15 +585,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { OS << "\n"; } - // Return the appropriate status when verifying diagnostics. - // - // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need - // this. - if (getDiagnosticOpts().VerifyDiagnostics) - return !static_cast<VerifyDiagnosticsClient&>( - getDiagnosticClient()).HadErrors(); - - return !getDiagnostics().getNumErrors(); + return !getDiagnostics().getClient()->getNumErrors(); } |