Add CompilerInvocation object, to capture all the options one needs to invoke

the compiler, and start flood filling it into clang-cc.

llvm-svn: 86586
This commit is contained in:
Daniel Dunbar 2009-11-09 20:55:08 +00:00
parent 0bf69cc7b7
commit b2eae89108
2 changed files with 101 additions and 43 deletions

View File

@ -0,0 +1,43 @@
//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
#include "clang/Frontend/DiagnosticOptions.h"
#include <string>
namespace clang {
/// CompilerInvocation - Helper class for holding the data necessary to invoke
/// the compiler.
///
/// This class is designed to represent an abstract "invocation" of the
/// compiler, including data such as the include paths, the code generation
/// options, the warning flags, and so on.
class CompilerInvocation {
/// The location for the output file. This is optional only for compiler
/// invocations which have no output.
std::string OutputFile;
DiagnosticOptions Diags;
public:
CompilerInvocation() {}
std::string &getOutputFile() { return OutputFile; }
const std::string &getOutputFile() const { return OutputFile; }
DiagnosticOptions &getDiagnosticOpts() { return Diags; }
const DiagnosticOptions &getDiagnosticOpts() const { return Diags; }
};
} // end namespace clang
#endif

View File

@ -25,6 +25,7 @@
#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/CompileOptions.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FixItRewriter.h"
@ -269,8 +270,6 @@ TokenCache("token-cache", llvm::cl::value_desc("path"),
// Diagnostic Options
//===----------------------------------------------------------------------===//
static DiagnosticOptions DiagOpts;
static llvm::cl::opt<bool>
VerifyDiagnostics("verify",
llvm::cl::desc("Verify emitted diagnostics and warnings"));
@ -1590,11 +1589,13 @@ class LoggingDiagnosticClient : public DiagnosticClient {
llvm::OwningPtr<DiagnosticClient> Chain2;
public:
LoggingDiagnosticClient(DiagnosticClient *Normal) {
LoggingDiagnosticClient(const CompilerInvocation &CompOpts,
DiagnosticClient *Normal) {
// Output diags both where requested...
Chain1.reset(Normal);
// .. and to our log file.
Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile,
CompOpts.getDiagnosticOpts()));
}
virtual void BeginSourceFile(const LangOptions &LO) {
@ -1619,7 +1620,8 @@ public:
};
} // end anonymous namespace.
static void SetUpBuildDumpLog(unsigned argc, char **argv,
static void SetUpBuildDumpLog(const CompilerInvocation &CompOpts,
unsigned argc, char **argv,
llvm::OwningPtr<DiagnosticClient> &DiagClient) {
std::string ErrorInfo;
@ -1642,7 +1644,7 @@ static void SetUpBuildDumpLog(unsigned argc, char **argv,
// LoggingDiagnosticClient - Insert a new logging diagnostic client in between
// the diagnostic producers and the normal receiver.
DiagClient.reset(new LoggingDiagnosticClient(DiagClient.take()));
DiagClient.reset(new LoggingDiagnosticClient(CompOpts, DiagClient.take()));
}
@ -1651,14 +1653,15 @@ static void SetUpBuildDumpLog(unsigned argc, char **argv,
// Main driver
//===----------------------------------------------------------------------===//
static llvm::raw_ostream *ComputeOutFile(const std::string &InFile,
static llvm::raw_ostream *ComputeOutFile(const CompilerInvocation &CompOpts,
const std::string &InFile,
const char *Extension,
bool Binary,
llvm::sys::Path& OutPath) {
llvm::raw_ostream *Ret;
std::string OutFile;
if (!OutputFile.empty())
OutFile = OutputFile;
if (!CompOpts.getOutputFile().empty())
OutFile = CompOpts.getOutputFile();
else if (InFile == "-") {
OutFile = "-";
} else if (Extension) {
@ -1685,7 +1688,8 @@ static llvm::raw_ostream *ComputeOutFile(const std::string &InFile,
return Ret;
}
static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
static ASTConsumer *CreateConsumerAction(const CompilerInvocation &CompOpts,
Preprocessor &PP,
const std::string &InFile,
ProgActions PA,
llvm::OwningPtr<llvm::raw_ostream> &OS,
@ -1697,11 +1701,11 @@ static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
return 0;
case ASTPrint:
OS.reset(ComputeOutFile(InFile, 0, false, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, false, OutPath));
return CreateASTPrinter(OS.get());
case ASTPrintXML:
OS.reset(ComputeOutFile(InFile, "xml", false, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, "xml", false, OutPath));
return CreateASTPrinterXML(OS.get());
case ASTDump:
@ -1726,15 +1730,15 @@ static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
BackendAction Act;
if (ProgAction == EmitAssembly) {
Act = Backend_EmitAssembly;
OS.reset(ComputeOutFile(InFile, "s", true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, "s", true, OutPath));
} else if (ProgAction == EmitLLVM) {
Act = Backend_EmitLL;
OS.reset(ComputeOutFile(InFile, "ll", true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, "ll", true, OutPath));
} else if (ProgAction == EmitLLVMOnly) {
Act = Backend_EmitNothing;
} else {
Act = Backend_EmitBC;
OS.reset(ComputeOutFile(InFile, "bc", true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, "bc", true, OutPath));
}
CompileOptions Opts;
@ -1744,7 +1748,7 @@ static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
}
case RewriteObjC:
OS.reset(ComputeOutFile(InFile, "cpp", true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, "cpp", true, OutPath));
return CreateObjCRewriter(InFile, OS.get(), PP.getDiagnostics(),
PP.getLangOptions(), SilenceRewriteMacroWarning);
@ -1756,7 +1760,8 @@ static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
/// ProcessInputFile - Process a single input file with the specified state.
///
static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
static void ProcessInputFile(const CompilerInvocation &CompOpts,
Preprocessor &PP, const std::string &InFile,
ProgActions PA,
const llvm::StringMap<bool> &Features,
llvm::LLVMContext& Context) {
@ -1769,7 +1774,7 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
switch (PA) {
default:
Consumer.reset(CreateConsumerAction(PP, InFile, PA, OS, OutPath,
Consumer.reset(CreateConsumerAction(CompOpts, PP, InFile, PA, OS, OutPath,
Features, Context));
if (!Consumer.get()) {
@ -1781,12 +1786,12 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
break;;
case EmitHTML:
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
Consumer.reset(CreateHTMLPrinter(OS.get(), PP));
break;
case RunAnalysis:
Consumer.reset(CreateAnalysisConsumer(PP, OutputFile,
Consumer.reset(CreateAnalysisConsumer(PP, CompOpts.getOutputFile(),
ReadAnalyzerOptions()));
break;
@ -1796,7 +1801,7 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
RelocatablePCH.setValue(false);
}
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
if (RelocatablePCH.getValue())
Consumer.reset(CreatePCHGenerator(PP, OS.get(), isysroot.c_str()));
else
@ -1839,20 +1844,20 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
case GeneratePTH: {
llvm::TimeRegion Timer(ClangFrontendTimer);
if (OutputFile.empty() || OutputFile == "-") {
if (CompOpts.getOutputFile().empty() || CompOpts.getOutputFile() == "-") {
// FIXME: Don't fail this way.
// FIXME: Verify that we can actually seek in the given file.
llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
::exit(1);
}
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
CacheTokens(PP, static_cast<llvm::raw_fd_ostream*>(OS.get()));
ClearSourceMgr = true;
break;
}
case PrintPreprocessedInput:
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
break;
case ParseNoop:
@ -1860,7 +1865,7 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
case ParsePrintCallbacks: {
llvm::TimeRegion Timer(ClangFrontendTimer);
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
ParseFile(PP, CreatePrintParserActionsAction(PP, OS.get()));
ClearSourceMgr = true;
break;
@ -1873,13 +1878,13 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
}
case RewriteMacros:
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
RewriteMacrosInInput(PP, OS.get());
ClearSourceMgr = true;
break;
case RewriteTest:
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
OS.reset(ComputeOutFile(CompOpts, InFile, 0, true, OutPath));
DoRewriteTest(PP, OS.get());
ClearSourceMgr = true;
break;
@ -2058,7 +2063,7 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
}
if (FixItRewrite)
FixItRewrite->WriteFixedFile(InFile, OutputFile);
FixItRewrite->WriteFixedFile(InFile, CompOpts.getOutputFile());
// Disable the consumer prior to the context, the consumer may perform actions
// in its destructor which require the context.
@ -2103,7 +2108,8 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
/// ProcessInputFile - Process a single AST input file with the specified state.
///
static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
static void ProcessASTInputFile(const CompilerInvocation &CompOpts,
const std::string &InFile, ProgActions PA,
const llvm::StringMap<bool> &Features,
Diagnostic &Diags, FileManager &FileMgr,
llvm::LLVMContext& Context) {
@ -2118,7 +2124,8 @@ static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
llvm::OwningPtr<llvm::raw_ostream> OS;
llvm::sys::Path OutPath;
llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(PP, InFile, PA, OS,
llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(CompOpts, PP,
InFile, PA, OS,
OutPath, Features,
Context));
@ -2172,6 +2179,20 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) {
exit(1);
}
static void ConstructCompilerInvocation(CompilerInvocation &Opts) {
Opts.getOutputFile() = OutputFile;
// Initialize the diagnostic options.
Opts.getDiagnosticOpts().ShowColumn = !NoShowColumn;
Opts.getDiagnosticOpts().ShowLocation = !NoShowLocation;
Opts.getDiagnosticOpts().ShowCarets = !NoCaretDiagnostics;
Opts.getDiagnosticOpts().ShowFixits = !NoDiagnosticsFixIt;
Opts.getDiagnosticOpts().ShowSourceRanges = PrintSourceRangeInfo;
Opts.getDiagnosticOpts().ShowOptionNames = PrintDiagnosticOption;
Opts.getDiagnosticOpts().ShowColors = PrintColorDiagnostic;
Opts.getDiagnosticOpts().MessageLength = MessageLength;
}
int main(int argc, char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
@ -2196,15 +2217,8 @@ int main(int argc, char **argv) {
if (InputFilenames.empty())
InputFilenames.push_back("-");
// Initialize the diagnostic options.
DiagOpts.ShowColumn = !NoShowColumn;
DiagOpts.ShowLocation = !NoShowLocation;
DiagOpts.ShowCarets = !NoCaretDiagnostics;
DiagOpts.ShowFixits = !NoDiagnosticsFixIt;
DiagOpts.ShowSourceRanges = PrintSourceRangeInfo;
DiagOpts.ShowOptionNames = PrintDiagnosticOption;
DiagOpts.ShowColors = PrintColorDiagnostic;
DiagOpts.MessageLength = MessageLength;
CompilerInvocation CompOpts;
ConstructCompilerInvocation(CompOpts);
// Create the diagnostic client for reporting errors or for
// implementing -verify.
@ -2217,11 +2231,12 @@ int main(int argc, char **argv) {
return 1;
}
} else {
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(),
CompOpts.getDiagnosticOpts()));
}
if (!DumpBuildInformation.empty())
SetUpBuildDumpLog(argc, argv, DiagClient);
SetUpBuildDumpLog(CompOpts, argc, argv, DiagClient);
// Configure our handling of diagnostics.
Diagnostic Diags(DiagClient.get());
@ -2278,7 +2293,7 @@ int main(int argc, char **argv) {
LangKind LK = GetLanguage(InFile);
// AST inputs are handled specially.
if (LK == langkind_ast) {
ProcessASTInputFile(InFile, ProgAction, Features,
ProcessASTInputFile(CompOpts, InFile, ProgAction, Features,
Diags, FileMgr, Context);
continue;
}
@ -2335,7 +2350,7 @@ int main(int argc, char **argv) {
// Process the source file.
DiagClient->BeginSourceFile(LangInfo);
ProcessInputFile(*PP, InFile, ProgAction, Features, Context);
ProcessInputFile(CompOpts, *PP, InFile, ProgAction, Features, Context);
DiagClient->EndSourceFile();
HeaderInfo.ClearFileInfo();