diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index 05fadf5a03446..a866f621c1003 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -3364,7 +3364,7 @@ Multiple occurrences accumulate prefixes. For example, Specifying Diagnostics ^^^^^^^^^^^^^^^^^^^^^^ -Indicating that a line expects an error or a warning is simple. Put a comment +Indicating that a line expects an error or a warning is easy. Put a comment on the line that has the diagnostic, use ``expected-{error,warning,remark,note}`` to tag if it's an expected error, warning, remark, or note (respectively), and place the expected text between @@ -3373,6 +3373,9 @@ enough to ensure that the correct diagnostic was emitted. (Note: full text should be included in test cases unless there is a compelling reason to use truncated text instead.) +For a full description of the matching behavior, including more complex +matching scenarios, see :ref:`matching ` below. + Here's an example of the most commonly used way to specify expected diagnostics: @@ -3458,8 +3461,33 @@ A range can also be specified by ``-``. For example: In this example, the diagnostic may appear only once, if at all. +.. _DiagnosticMatching: + +Matching Modes +~~~~~~~~~~~~~~ + +The default matching mode is simple string, which looks for the expected text +that appears between the first `{{` and `}}` pair of the comment. The string is +interpreted just as-is, with one exception: the sequence `\n` is converted to a +single newline character. This mode matches the emitted diagnostic when the +text appears as a substring at any position of the emitted message. + +To enable matching against desired strings that contain `}}` or `{{`, the +string-mode parser accepts opening delimiters of more than two curly braces, +like `{{{`. It then looks for a closing delimiter of equal "width" (i.e `}}}`). +For example: + +.. code-block:: c++ + + // expected-note {{{evaluates to '{{2, 3, 4}} == {0, 3, 4}'}}} + +The intent is to allow the delimeter to be wider than the longest `{` or `}` +brace sequence in the content, so that if your expected text contains `{{{` +(three braces) it may be delimited with `{{{{` (four braces), and so on. + Regex matching mode may be selected by appending ``-re`` to the diagnostic type -and including regexes wrapped in double curly braces in the directive, such as: +and including regexes wrapped in double curly braces (`{{` and `}}`) in the +directive, such as: .. code-block:: text @@ -3471,6 +3499,8 @@ Examples matching error: "variable has incomplete type 'struct s'" // expected-error {{variable has incomplete type 'struct s'}} // expected-error {{variable has incomplete type}} + // expected-error {{{variable has incomplete type}}} + // expected-error {{{{variable has incomplete type}}}} // expected-error-re {{variable has type 'struct {{.}}'}} // expected-error-re {{variable has type 'struct {{.*}}'}} diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 568000106a84d..85ecfdf9de62d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -167,7 +167,7 @@ def err_verify_no_such_marker : Error< def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< - "cannot find end ('}}') of expected %0">; + "cannot find end ('%1') of expected %0">; def err_verify_invalid_content : Error< "invalid expected %0: %1">; def err_verify_missing_regex : Error< diff --git a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp index 8a3d2286cd168..f508408ba7062 100644 --- a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -611,12 +611,19 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, diag::err_verify_missing_start) << KindStr; continue; } + llvm::SmallString<8> CloseBrace("}}"); + const char *const DelimBegin = PH.C; PH.Advance(); + // Count the number of opening braces for `string` kinds + for (; !D.RegexKind && PH.Next("{"); PH.Advance()) + CloseBrace += '}'; const char* const ContentBegin = PH.C; // mark content begin - // Search for token: }} - if (!PH.SearchClosingBrace("{{", "}}")) { - Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), - diag::err_verify_missing_end) << KindStr; + // Search for closing brace + StringRef OpenBrace(DelimBegin, ContentBegin - DelimBegin); + if (!PH.SearchClosingBrace(OpenBrace, CloseBrace)) { + Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin), + diag::err_verify_missing_end) + << KindStr << CloseBrace; continue; } const char* const ContentEnd = PH.P; // mark content end diff --git a/clang/test/Frontend/verify.c b/clang/test/Frontend/verify.c index 221b715c19e41..c549011d7b7a9 100644 --- a/clang/test/Frontend/verify.c +++ b/clang/test/Frontend/verify.c @@ -157,3 +157,33 @@ unexpected b; // expected-error@33 1-1 {{unknown type}} // what-error {{huh?}} // CHECK9: error: 'what-error' diagnostics expected but not seen: #endif + +#ifdef TEST_WIDE_DELIM +// RUN: not %clang_cc1 -DTEST_WIDE_DELIM -verify %s 2>&1 | FileCheck -check-prefix=CHECK-WIDE-DELIM %s + +// expected-error {{{some message with {{}} in it}}} +// expected-error {{{some message with {}} in it}}} +// expected-error {{{some message with {{} in it}}} + +// expected-error-re {{{some {{.*}} regex with double braces}}} +// expected-error-re {{{some message with {{} in it}}} + +// expected-error {{{mismatched delim}} +// expected-error-re {{{mismatched re {{.*} }}} +// expected-error-re {{{no regex}}} + +#if 0 +// CHECK-WIDE-DELIM: error: 'expected-error' diagnostics expected but not seen: +// CHECK-WIDE-DELIM-NEXT: verify.c Line 164: some message with {{[{]{}[}]}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 165: some message with {}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 166: some message with {{[{]{[}]}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 168: {some {{.*}} regex with double braces +// CHECK-WIDE-DELIM-NEXT: error: 'expected-error' diagnostics seen but not expected: +// CHECK-WIDE-DELIM-NEXT: verify.c Line 169: cannot find end ('}}') of expected regex +// CHECK-WIDE-DELIM-NEXT: verify.c Line 171: cannot find end ('}}}') of expected string +// CHECK-WIDE-DELIM-NEXT: verify.c Line 172: cannot find end ('}}') of expected regex +// CHECK-WIDE-DELIM-NEXT: verify.c Line 173: cannot find start of regex ('{{[{][{]}}') in {no regex +// CHECK-WIDE-DELIM-NEXT: 8 errors generated. +#endif + +#endif