]> granicus.if.org Git - clang/commitdiff
[driver] Parse diagnostic args in the driver.
authorChad Rosier <mcrosier@apple.com>
Tue, 13 Mar 2012 20:09:56 +0000 (20:09 +0000)
committerChad Rosier <mcrosier@apple.com>
Tue, 13 Mar 2012 20:09:56 +0000 (20:09 +0000)
Previously, only diagnostics thrown by the cc1 process were
actually honoring the diagnostic options given on the command line,
like -Werror.

Reuse the existing code in Frontend currently used for cc1,
adjusting it to not interpret -Wl, linker flags as warnings.

Also fix a faulty test exposed by this change.
It wasn't actually testing anything, and was giving this warning:

clang-3: warning: argument unused during compilation: '-verify'

Which -Werror didn't turn into an error because it was output
by the driver, not the cc1 process, and diagnostic options
weren't parsed by the driver. And you couldn't see the warning
when running the test suite.

Fixes PR12181.
Patch by Dylan Noblesmith <nobled@dreamwidth.org>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152660 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/ArgList.h
include/clang/Frontend/CompilerInvocation.h
lib/Driver/ArgList.cpp
lib/Frontend/CompilerInvocation.cpp
test/Driver/diagnostics.c [new file with mode: 0644]
test/Driver/no-objc-arr.m
tools/driver/driver.cpp

index f9698048b2bd12cb80d65ddc82e27ac6556d42f9..3affb009fc37a80a453dce8c7fae66ae772b73e2 100644 (file)
@@ -204,10 +204,18 @@ namespace driver {
     StringRef getLastArgValue(OptSpecifier Id,
                                     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.
index 0099aae8dc9e39c0aa681083a2000843f034922c..0d2260acbc691a9fe7471755f9b65a90f0a0bd59 100644 (file)
@@ -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:
index d26da25b3e300007272dc11b6b7363dd28b8c9e8..55a0ddfd272a24c5b239397b470696ae4d9dd728 100644 (file)
@@ -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;
index 7f7f35cc09935161d366f2a1982728166345cd7a..13a9897f0715ede653100abfef5a89501c51b161 100644 (file)
@@ -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 (file)
index 0000000..1330041
--- /dev/null
@@ -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 
index 15fbdc20ce8a76c9c21d40f4096fb67b7014c2e3..e44939337a6afed5f1a61ad7b27c54aec730523e 100644 (file)
@@ -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() {
index 9e666eb43f2143393067b230e82aa5b35043ce65..8c05fff4dee93bbc56e1039c34660becba2e038a 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#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;