summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/Driver/ArgList.h10
-rw-r--r--include/clang/Frontend/CompilerInvocation.h11
-rw-r--r--lib/Driver/ArgList.cpp10
-rw-r--r--lib/Frontend/CompilerInvocation.cpp37
-rw-r--r--test/Driver/diagnostics.c9
-rw-r--r--test/Driver/no-objc-arr.m2
-rw-r--r--tools/driver/driver.cpp23
7 files changed, 83 insertions, 19 deletions
diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h
index f9698048b2..3affb009fc 100644
--- a/include/clang/Driver/ArgList.h
+++ b/include/clang/Driver/ArgList.h
@@ -205,9 +205,17 @@ namespace driver {
StringRef Default = "") const;
/// getLastArgValue - Return the value of the last argument as an integer,
+ /// or a default. If Diags is non-null, emits an error if the argument
+ /// is given, but non-integral.
+ int getLastArgIntValue(OptSpecifier Id, int Default,
+ DiagnosticsEngine *Diags = 0) const;
+
+ /// getLastArgValue - Return the value of the last argument as an integer,
/// or a default. Emits an error if the argument is given, but non-integral.
int getLastArgIntValue(OptSpecifier Id, int Default,
- DiagnosticsEngine &Diags) const;
+ DiagnosticsEngine &Diags) const {
+ return getLastArgIntValue(Id, Default, &Diags);
+ }
/// getAllArgValues - Get the values of all instances of the given argument
/// as strings.
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 0099aae8dc..0d2260acbc 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -33,6 +33,17 @@ namespace clang {
class CompilerInvocation;
class DiagnosticsEngine;
+
+namespace driver {
+class ArgList;
+}
+
+/// CompilerInvocation - Fill out Opts based on the options given in Args.
+/// Args must have been created from the OptTable returned by
+/// createCC1OptTable(). When errors are encountered, return false and,
+/// if Diags is non-null, report the error(s).
+bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args,
+ DiagnosticsEngine *Diags = 0);
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
protected:
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
index d26da25b3e..55a0ddfd27 100644
--- a/lib/Driver/ArgList.cpp
+++ b/lib/Driver/ArgList.cpp
@@ -154,13 +154,15 @@ StringRef ArgList::getLastArgValue(OptSpecifier Id,
}
int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
- clang::DiagnosticsEngine &Diags) const {
+ clang::DiagnosticsEngine *Diags) const {
int Res = Default;
if (Arg *A = getLastArg(Id)) {
- if (StringRef(A->getValue(*this)).getAsInteger(10, Res))
- Diags.Report(diag::err_drv_invalid_int_value)
- << A->getAsString(*this) << A->getValue(*this);
+ if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) {
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_int_value)
+ << A->getAsString(*this) << A->getValue(*this);
+ }
}
return Res;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 7f7f35cc09..13a9897f07 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1277,8 +1277,8 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
}
-static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags) {
+bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+ DiagnosticsEngine *Diags) {
using namespace cc1options;
bool Success = true;
@@ -1312,10 +1312,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
else if (ShowOverloads == "all")
Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
else {
- Diags.Report(diag::err_drv_invalid_value)
+ Success = false;
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_value)
<< Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
<< ShowOverloads;
- Success = false;
}
StringRef ShowCategory =
@@ -1327,10 +1328,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
else if (ShowCategory == "name")
Opts.ShowCategories = 2;
else {
- Diags.Report(diag::err_drv_invalid_value)
+ Success = false;
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_value)
<< Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
<< ShowCategory;
- Success = false;
}
StringRef Format =
@@ -1342,10 +1344,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
else if (Format == "vi")
Opts.Format = DiagnosticOptions::Vi;
else {
- Diags.Report(diag::err_drv_invalid_value)
+ Success = false;
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_value)
<< Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
<< Format;
- Success = false;
}
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
@@ -1366,13 +1369,23 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
- Diags.Report(diag::warn_ignoring_ftabstop_value)
- << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
Opts.TabStop = DiagnosticOptions::DefaultTabStop;
+ if (Diags)
+ Diags->Report(diag::warn_ignoring_ftabstop_value)
+ << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
}
Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
- Opts.Warnings = Args.getAllArgValues(OPT_W);
+
+ for (arg_iterator it = Args.filtered_begin(OPT_W),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ StringRef V = (*it)->getValue(Args);
+ // "-Wl," and such are not warnings options.
+ if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
+ continue;
+
+ Opts.Warnings.push_back(V);
+ }
return Success;
}
@@ -2174,7 +2187,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
- Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags)
+ Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, &Diags)
&& Success;
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
// FIXME: We shouldn't have to pass the DashX option around here
diff --git a/test/Driver/diagnostics.c b/test/Driver/diagnostics.c
new file mode 100644
index 0000000000..1330041ae4
--- /dev/null
+++ b/test/Driver/diagnostics.c
@@ -0,0 +1,9 @@
+// Parse diagnostic arguments in the driver
+// PR12181
+
+// RUN: !%clang -target x86_64-apple-darwin10 \
+// RUN: -fsyntax-only -fzyzzybalubah \
+// RUN: -Werror=unused-command-line-argument %s
+
+// RUN: !%clang -target x86_64-apple-darwin10 \
+// RUN: -fsyntax-only -fzyzzybalubah -Werror %s
diff --git a/test/Driver/no-objc-arr.m b/test/Driver/no-objc-arr.m
index 15fbdc20ce..e44939337a 100644
--- a/test/Driver/no-objc-arr.m
+++ b/test/Driver/no-objc-arr.m
@@ -1,4 +1,4 @@
-// RUN: %clang -Werror -fobjc-arc -fsyntax-only -fno-objc-arc -verify %s
+// RUN: %clang -Werror -fobjc-arc -fsyntax-only -fno-objc-arc -Xclang -verify %s
// rdar://8949617
void * FOO() {
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 9e666eb43f..8c05fff4de 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -12,11 +12,16 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/CC1Options.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Option.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
@@ -370,11 +375,27 @@ int main(int argc_, const char **argv_) {
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
+ DiagnosticOptions DiagOpts;
+ {
+ // Note that ParseDiagnosticArgs() uses the cc1 option table.
+ OwningPtr<OptTable> CC1Opts(createCC1OptTable());
+ unsigned MissingArgIndex, MissingArgCount;
+ OwningPtr<InputArgList> Args(CC1Opts->ParseArgs(argv.begin()+1, argv.end(),
+ MissingArgIndex, MissingArgCount));
+ // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
+ // Any errors that would be diagnosed here will also be diagnosed later,
+ // when the DiagnosticsEngine actually exists.
+ (void) ParseDiagnosticArgs(DiagOpts, *Args);
+ }
+ // Now we can create the DiagnosticsEngine with a properly-filled-out
+ // DiagnosticOptions instance.
TextDiagnosticPrinter *DiagClient
- = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
+ = new TextDiagnosticPrinter(llvm::errs(), DiagOpts);
DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+
DiagnosticsEngine Diags(DiagID, DiagClient);
+ ProcessWarningOptions(Diags, DiagOpts);
#ifdef CLANG_IS_PRODUCTION
const bool IsProduction = true;