Index: include/clang/Basic/DiagnosticOptions.h =================================================================== --- include/clang/Basic/DiagnosticOptions.h +++ include/clang/Basic/DiagnosticOptions.h @@ -100,6 +100,10 @@ /// prefixes removed. std::vector 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) 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<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; +def verify_EQ : Joined<["-"], "verify=">, + MetaVarName<"">, + HelpText<"Verify diagnostic output using comment directives that start with ">; 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: 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: 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: 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