Change clang-cc to expect that all inputs have the same language (so we can only construct a single LangInfo). This matches how it is used in practice (since the compiler only it invokes it for one file at a time).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86609 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2009-11-09 22:45:57 +00:00
Родитель 094a84cc06
Коммит 227b2380f6
1 изменённых файлов: 79 добавлений и 48 удалений

Просмотреть файл

@ -60,6 +60,7 @@
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h" #include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
@ -436,28 +437,6 @@ static llvm::cl::opt<bool>
PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"), PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"),
llvm::cl::init(false)); llvm::cl::init(false));
static LangKind GetLanguage(llvm::StringRef Filename) {
if (BaseLang != langkind_unspecified)
return BaseLang;
return llvm::StringSwitch<LangKind>(Filename.rsplit('.').second)
.Case("ast", langkind_ast)
.Case("c", langkind_c)
.Cases("S", "s", langkind_asm_cpp)
.Case("i", langkind_c_cpp)
.Case("ii", langkind_cxx_cpp)
.Case("m", langkind_objc)
.Case("mi", langkind_objc_cpp)
.Cases("mm", "M", langkind_objcxx)
.Case("mii", langkind_objcxx_cpp)
.Case("C", langkind_cxx)
.Cases("C", "cc", "cp", langkind_cxx)
.Cases("cpp", "CPP", "c++", "cxx", langkind_cxx)
.Case("cl", langkind_ocl)
.Default(langkind_c);
}
static void InitializeCOptions(LangOptions &Options) { static void InitializeCOptions(LangOptions &Options) {
// Do nothing. // Do nothing.
} }
@ -715,7 +694,7 @@ StackProtector("stack-protector",
static void InitializeLanguageStandard(LangOptions &Options, LangKind LK, static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
TargetInfo *Target, TargetInfo *Target,
const llvm::StringMap<bool> &Features) { const llvm::StringMap<bool> &Features) {
// Allow the target to set the default the langauge options as it sees fit. // Allow the target to set the default the language options as it sees fit.
Target->getDefaultLangOptions(Options); Target->getDefaultLangOptions(Options);
// Pass the map of target features to the target for validation and // Pass the map of target features to the target for validation and
@ -1578,13 +1557,12 @@ class LoggingDiagnosticClient : public DiagnosticClient {
llvm::OwningPtr<DiagnosticClient> Chain2; llvm::OwningPtr<DiagnosticClient> Chain2;
public: public:
LoggingDiagnosticClient(const CompilerInvocation &CompOpts, LoggingDiagnosticClient(const DiagnosticOptions &DiagOpts,
DiagnosticClient *Normal) { DiagnosticClient *Normal) {
// Output diags both where requested... // Output diags both where requested...
Chain1.reset(Normal); Chain1.reset(Normal);
// .. and to our log file. // .. and to our log file.
Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
CompOpts.getDiagnosticOpts()));
} }
virtual void BeginSourceFile(const LangOptions &LO) { virtual void BeginSourceFile(const LangOptions &LO) {
@ -1609,7 +1587,7 @@ public:
}; };
} // end anonymous namespace. } // end anonymous namespace.
static void SetUpBuildDumpLog(const CompilerInvocation &CompOpts, static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
unsigned argc, char **argv, unsigned argc, char **argv,
llvm::OwningPtr<DiagnosticClient> &DiagClient) { llvm::OwningPtr<DiagnosticClient> &DiagClient) {
@ -1633,7 +1611,7 @@ static void SetUpBuildDumpLog(const CompilerInvocation &CompOpts,
// LoggingDiagnosticClient - Insert a new logging diagnostic client in between // LoggingDiagnosticClient - Insert a new logging diagnostic client in between
// the diagnostic producers and the normal receiver. // the diagnostic producers and the normal receiver.
DiagClient.reset(new LoggingDiagnosticClient(CompOpts, DiagClient.take())); DiagClient.reset(new LoggingDiagnosticClient(DiagOpts, DiagClient.take()));
} }
@ -2168,18 +2146,61 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) {
exit(1); exit(1);
} }
static void ConstructCompilerInvocation(CompilerInvocation &Opts) { static LangKind GetLanguage() {
Opts.getOutputFile() = OutputFile; // If -x was given, that's the language.
if (BaseLang != langkind_unspecified)
return BaseLang;
// Otherwise guess it from the input filenames;
LangKind LK = langkind_unspecified;
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
llvm::StringRef Name(InputFilenames[i]);
LangKind ThisKind = llvm::StringSwitch<LangKind>(Name.rsplit('.').second)
.Case("ast", langkind_ast)
.Case("c", langkind_c)
.Cases("S", "s", langkind_asm_cpp)
.Case("i", langkind_c_cpp)
.Case("ii", langkind_cxx_cpp)
.Case("m", langkind_objc)
.Case("mi", langkind_objc_cpp)
.Cases("mm", "M", langkind_objcxx)
.Case("mii", langkind_objcxx_cpp)
.Case("C", langkind_cxx)
.Cases("C", "cc", "cp", langkind_cxx)
.Cases("cpp", "CPP", "c++", "cxx", langkind_cxx)
.Case("cl", langkind_ocl)
.Default(langkind_c);
if (LK != langkind_unspecified && ThisKind != LK) {
llvm::errs() << "error: cannot have multiple input files of distinct "
<< "language kinds without -x\n";
exit(1);
}
LK = ThisKind;
}
return LK;
}
static void ConstructDiagnosticOptions(DiagnosticOptions &Opts) {
// Initialize the diagnostic options. // Initialize the diagnostic options.
Opts.getDiagnosticOpts().ShowColumn = !NoShowColumn; Opts.ShowColumn = !NoShowColumn;
Opts.getDiagnosticOpts().ShowLocation = !NoShowLocation; Opts.ShowLocation = !NoShowLocation;
Opts.getDiagnosticOpts().ShowCarets = !NoCaretDiagnostics; Opts.ShowCarets = !NoCaretDiagnostics;
Opts.getDiagnosticOpts().ShowFixits = !NoDiagnosticsFixIt; Opts.ShowFixits = !NoDiagnosticsFixIt;
Opts.getDiagnosticOpts().ShowSourceRanges = PrintSourceRangeInfo; Opts.ShowSourceRanges = PrintSourceRangeInfo;
Opts.getDiagnosticOpts().ShowOptionNames = PrintDiagnosticOption; Opts.ShowOptionNames = PrintDiagnosticOption;
Opts.getDiagnosticOpts().ShowColors = PrintColorDiagnostic; Opts.ShowColors = PrintColorDiagnostic;
Opts.getDiagnosticOpts().MessageLength = MessageLength; Opts.MessageLength = MessageLength;
}
static void ConstructCompilerInvocation(CompilerInvocation &Opts,
const DiagnosticOptions &DiagOpts,
const TargetInfo &Target) {
Opts.getDiagnosticOpts() = DiagOpts;
Opts.getOutputFile() = OutputFile;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -2206,8 +2227,10 @@ int main(int argc, char **argv) {
if (InputFilenames.empty()) if (InputFilenames.empty())
InputFilenames.push_back("-"); InputFilenames.push_back("-");
CompilerInvocation CompOpts; // Construct the diagnostic options first, which cannot fail, so that we can
ConstructCompilerInvocation(CompOpts); // build a diagnostic client to use for any errors during option handling.
DiagnosticOptions DiagOpts;
ConstructDiagnosticOptions(DiagOpts);
// Create the diagnostic client for reporting errors or for // Create the diagnostic client for reporting errors or for
// implementing -verify. // implementing -verify.
@ -2216,16 +2239,15 @@ int main(int argc, char **argv) {
// When checking diagnostics, just buffer them up. // When checking diagnostics, just buffer them up.
DiagClient.reset(new TextDiagnosticBuffer()); DiagClient.reset(new TextDiagnosticBuffer());
if (InputFilenames.size() != 1) { if (InputFilenames.size() != 1) {
fprintf(stderr, "-verify only works on single input files for now.\n"); fprintf(stderr, "-verify only works on single input files.\n");
return 1; return 1;
} }
} else { } else {
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
CompOpts.getDiagnosticOpts()));
} }
if (!DumpBuildInformation.empty()) if (!DumpBuildInformation.empty())
SetUpBuildDumpLog(CompOpts, argc, argv, DiagClient); SetUpBuildDumpLog(DiagOpts, argc, argv, DiagClient);
// Configure our handling of diagnostics. // Configure our handling of diagnostics.
Diagnostic Diags(DiagClient.get()); Diagnostic Diags(DiagClient.get());
@ -2266,6 +2288,17 @@ int main(int argc, char **argv) {
if (!InheritanceViewCls.empty()) // C++ visualization? if (!InheritanceViewCls.empty()) // C++ visualization?
ProgAction = InheritanceView; ProgAction = InheritanceView;
// Infer the input language.
//
// FIXME: We should move .ast inputs to taking a separate path, they are
// really quite different.
LangKind LK = GetLanguage();
// Now that we have initialized the diagnostics engine and the target, finish
// setting up the compiler invocation.
CompilerInvocation CompOpts;
ConstructCompilerInvocation(CompOpts, DiagOpts, *Target);
// Create the source manager. // Create the source manager.
SourceManager SourceMgr; SourceManager SourceMgr;
@ -2279,7 +2312,6 @@ int main(int argc, char **argv) {
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
const std::string &InFile = InputFilenames[i]; const std::string &InFile = InputFilenames[i];
LangKind LK = GetLanguage(InFile);
// AST inputs are handled specially. // AST inputs are handled specially.
if (LK == langkind_ast) { if (LK == langkind_ast) {
ProcessASTInputFile(CompOpts, InFile, ProgAction, Features, ProcessASTInputFile(CompOpts, InFile, ProgAction, Features,
@ -2293,7 +2325,6 @@ int main(int argc, char **argv) {
// Initialize language options, inferring file types from input filenames. // Initialize language options, inferring file types from input filenames.
LangOptions LangInfo; LangOptions LangInfo;
InitializeLangOptions(LangInfo, LK); InitializeLangOptions(LangInfo, LK);
InitializeLanguageStandard(LangInfo, LK, Target.get(), Features); InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
@ -2338,9 +2369,9 @@ int main(int argc, char **argv) {
} }
// Process the source file. // Process the source file.
DiagClient->BeginSourceFile(LangInfo); Diags.getClient()->BeginSourceFile(LangInfo);
ProcessInputFile(CompOpts, *PP, InFile, ProgAction, Features, Context); ProcessInputFile(CompOpts, *PP, InFile, ProgAction, Features, Context);
DiagClient->EndSourceFile(); Diags.getClient()->EndSourceFile();
HeaderInfo.ClearFileInfo(); HeaderInfo.ClearFileInfo();
} }