jdenny created this revision.

This mimic's FileCheck's --check-prefix option.

The default PREFIX is "expected".  That is, "-verify" is equivalent to
"-verify=expected".

The goal is to permit exercising a single test suite source file with
different compiler options producing different sets of diagnostics.
While cpp can be combined with the existing -verify to accomplish the
same goal, source is often easier to read when it's not cluttered with
preprocessor directives.  For those cases, this tiny extension seems
worthwhile.


https://reviews.llvm.org/D39694

Files:
  include/clang/Basic/DiagnosticOptions.h
  include/clang/Driver/CC1Options.td
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/VerifyDiagnosticConsumer.cpp
  test/Frontend/verify-prefix.c

Index: test/Frontend/verify-prefix.c
===================================================================
--- /dev/null
+++ test/Frontend/verify-prefix.c
@@ -0,0 +1,38 @@
+// gconst-note@2 {{variable 'glb' declared const here}}
+GC int glb = 5;
+
+// Check various -verify prefixes.
+// RUN: %clang_cc1             -DGC=const -DLC=      -DSC= -verify=gconst %s
+// RUN: %clang_cc1 -Wcast-qual -DGC=      -DLC=const -DSC= -verify=lconst %s
+// RUN: %clang_cc1             -DGC=      -DLC=      -DSC= -verify=nconst %s
+
+// Check empty -verify prefix.  Make sure there's no additional output, which
+// might indicate diagnostic verification became enabled even though it was
+// requested incorrectly.
+// RUN: not %clang_cc1 -DGC=const -DLC=const -DSC=const -verify= %s 2> %t
+// RUN: FileCheck --check-prefix=EMPTY %s < %t
+// EMPTY-NOT: {{.}}
+// EMPTY:     error: invalid value '' in '-verify='
+// EMPTY-NOT: {{.}}
+
+// Check omitting the -verify prefix.
+// RUN: %clang_cc1 -DGC= -DLC= -DSC=const -verify %s
+
+// Check omitting -verify: check that code actually has expected diagnostics.
+// RUN: not %clang_cc1 -Wcast-qual -DGC=const -DLC=const -DSC=const %s 2> %t
+// RUN: FileCheck --check-prefix=ALL %s < %t
+// ALL: cannot assign to variable 'glb' with const-qualified type 'const int'
+// ALL: variable 'glb' declared const here
+// ALL: cast from 'const int *' to 'int *' drops const qualifier
+// ALL: initializing 'int *' with an expression of type 'const int *' discards qualifiers
+
+void foo() {
+  LC int loc = 5;
+  SC static int sta = 5;
+  glb = 6; // gconst-error {{cannot assign to variable 'glb' with const-qualified type 'const int'}}
+  // lconst-warning@+1 {{cast from 'const int *' to 'int *' drops const qualifier}}
+  *(int*)(&loc) = 6;
+  int *p = &sta; // expected-warning {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}}
+}
+
+// nconst-no-diagnostics
Index: lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -315,7 +315,7 @@
   bool FoundDirective = false;
   for (ParseHelper PH(S); !PH.Done();) {
     // Search for token: expected
-    if (!PH.Search("expected", true))
+    if (!PH.Search(Diags.getDiagnosticOptions().VerifyPrefix, true))
       break;
     PH.Advance();
 
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1146,7 +1146,17 @@
   Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
   Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
   Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
-  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
+  Opts.VerifyPrefix = Args.getLastArgValue(OPT_verify_EQ, "expected");
+  if (Opts.VerifyPrefix.empty()) {
+    Success = false;
+    Opts.VerifyDiagnostics = false;
+    if (Diags) {
+      Arg *A = Args.getLastArg(OPT_verify_EQ);
+      Diags->Report(diag::err_drv_invalid_value)
+        << A->getAsString(Args) << A->getValue();
+    }
+  }
   DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
   Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
     Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -398,8 +398,11 @@
   HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
 def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
   HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def verify_EQ : Joined<["-"], "verify=">,
+  MetaVarName<"<prefix>">,
+  HelpText<"Verify diagnostic output using comment directives that start with <prefix>">;
 def verify : Flag<["-"], "verify">,
-  HelpText<"Verify diagnostic output using comment directives">;
+  HelpText<"Equivalent to -verify=expected">;
 def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
   HelpText<"Ignore unexpected diagnostic messages">;
 def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
Index: include/clang/Basic/DiagnosticOptions.h
===================================================================
--- include/clang/Basic/DiagnosticOptions.h
+++ include/clang/Basic/DiagnosticOptions.h
@@ -100,6 +100,10 @@
   /// prefixes removed.
   std::vector<std::string> Remarks;
 
+  /// The prefix for comment directives sought by -verify ("expected" by
+  /// default).
+  std::string VerifyPrefix;
+
 public:
   // Define accessors/mutators for diagnostic options of enumeration type.
 #define DIAGOPT(Name, Bits, Default)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to