[clang] [Clang] Wide delimiters ('{{{') for expect strings (PR #77326)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 9 07:46:27 PST 2024
https://github.com/sethp updated https://github.com/llvm/llvm-project/pull/77326
>From cd0b9aed2d9e53f9b38aaa0f73336acae06bfbee Mon Sep 17 00:00:00 2001
From: Seth Pellegrino <seth at codecopse.net>
Date: Sat, 6 Jan 2024 07:54:31 -0800
Subject: [PATCH 1/4] [Clang] Wide delimiters ('{{{') for expect strings
Prior to this commit, it was impossible to use the simple string
matching directives to look for most content that contains `{{`, such
as:
```
// expected-note {{my_struct{{1}, 2}}}
```
Which would parse like so:
```
"nested" brace v
// expected-note {{my_struct{{1}, 2}}}
closes the nested brace ^ |
trailing }
```
And the frontend would complain 'cannot find end ('}}') of expected'.
At this snapshot, VerifyDiagnosticConsumer's parser now counts the
opening braces and looks for a matching length of closing sigils,
allowing the above to be written as:
```
// expected-note {{{my_struct{{1}, 2}}}}
opening brace |-| |-|
closing brace is '}}}', found here ^
```
---
.../clang/Basic/DiagnosticFrontendKinds.td | 2 +-
clang/lib/Frontend/VerifyDiagnosticConsumer.cpp | 15 +++++++++++----
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 715e0c0dc8fa84..4bf0ab54a046c1 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -166,7 +166,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 ab8174f4f4db92..5eab7bd3619f19 100644
--- a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -612,12 +612,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
>From 4922ee24a26da88dab73d55b59f8aa53c3077f13 Mon Sep 17 00:00:00 2001
From: Seth Pellegrino <seth at codecopse.net>
Date: Mon, 8 Jan 2024 09:04:41 -0800
Subject: [PATCH 2/4] fixup!: update docs
---
clang/docs/InternalsManual.rst | 35 ++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst
index 05fadf5a034464..d98f228fdf2c7b 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 <DiagnosticMatching>` below.
+
Here's an example of the most commonly used way to specify expected
diagnostics:
@@ -3458,8 +3461,34 @@ A range can also be specified by ``<n>-<m>``. 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}'}}}
+
+If your expected text contains `{{{` (three braces), then it may be delimited
+with `{{{{` (four braces), and so on. If your expected text contains enough
+repeated `{`s to fill up a `ptrdiff_t`, then you'll definitely crash the
+parser, possibly even as late as the delimiter handling.
+
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 +3500,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 {{.*}}'}}
>From 38ca2d630f3b53aed3a54856e48546b865c42ac2 Mon Sep 17 00:00:00 2001
From: Seth Pellegrino <seth at codecopse.net>
Date: Mon, 8 Jan 2024 10:39:13 -0800
Subject: [PATCH 3/4] fixup!: add test
---
clang/test/Frontend/verify.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/clang/test/Frontend/verify.c b/clang/test/Frontend/verify.c
index 221b715c19e416..c549011d7b7a9a 100644
--- a/clang/test/Frontend/verify.c
+++ b/clang/test/Frontend/verify.c
@@ -157,3 +157,33 @@ unexpected b; // expected-error at 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
>From 019a8e0c598c32eb00d656bc4fbc3d740da6efb0 Mon Sep 17 00:00:00 2001
From: sethp <seth.pellegrino at gmail.com>
Date: Tue, 9 Jan 2024 07:46:19 -0800
Subject: [PATCH 4/4] fixup!: Update clang/docs/InternalsManual.rst
Review feedback
---
clang/docs/InternalsManual.rst | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst
index d98f228fdf2c7b..a866f621c1003b 100644
--- a/clang/docs/InternalsManual.rst
+++ b/clang/docs/InternalsManual.rst
@@ -3481,10 +3481,9 @@ For example:
// expected-note {{{evaluates to '{{2, 3, 4}} == {0, 3, 4}'}}}
-If your expected text contains `{{{` (three braces), then it may be delimited
-with `{{{{` (four braces), and so on. If your expected text contains enough
-repeated `{`s to fill up a `ptrdiff_t`, then you'll definitely crash the
-parser, possibly even as late as the delimiter handling.
+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 (`{{` and `}}`) in the
More information about the cfe-commits
mailing list