Skip to content

Commit e1a4ef5

Browse files
[clang][Parse] Stop parsing declarator chunks after a parenthesized structured binding (#219270)
Fixes #218144 Fixes #193687 `ParseDirectDeclarator` stops right after a structured binding like `[a, b]`, since nothing can follow it — but that check only covers the unparenthesized form. For `([a, b])`, the binding gets parsed inside `ParseParenDeclarator`, and the outer `ParseDirectDeclarator` doesn't notice — it carries on into its suffix loop and parses a trailing `()` as a function declarator. `([a, b])() {}` then looks like a function definition, so `ActOnStartOfFunctionDef` gets handed a `DecompositionDecl` where it expects a `FunctionDecl`: `cast<FunctionDecl>` asserts, or segfaults later without assertions — that's #193687. (The `b;` in the report is noise; `([a])() {}` alone crashes.) This patch makes `ParseDirectDeclarator` stop as well when the parenthesized declarator turns out to be a structured binding, so nothing can follow a binding list, parenthesized or not. The declaration then takes the normal variable path and hits the diagnostics we already have — `structured binding declaration cannot be declared with parentheses`, then `expected expression` for the empty `()` — same as `[a, b]() {}` today. No Sema changes; the parser just stops building a declarator that can't exist. LLM tools were used for this contribution. I've reviewed, built, and tested the change myself before pushing.
1 parent 63b4d98 commit e1a4ef5

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

clang/docs/ReleaseNotes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ features cannot lower the translation-unit ABI level;
503503
parsed where a nested-name-specifier could appear (e.g. ``int decltype = 0;``).
504504
Clang now diagnoses the error instead of asserting. (#GH211207)
505505

506+
- Fixed an assertion failure when a parenthesized structured binding declarator
507+
was followed by a function declarator and body (e.g. ``([a, b])() {}``).
508+
(#GH218144, #GH193687)
509+
506510
- Fixed a crash when computing the implicit deletion of a defaulted comparison
507511
operator required an access check that ran while an enclosing declaration
508512
was still being parsed. (#GH210692)

clang/lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6862,6 +6862,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
68626862
// Example: 'char (*X)' or 'int (*XX)(void)'
68636863
ParseParenDeclarator(D);
68646864

6865+
// As above, a structured binding declarator cannot be followed by any
6866+
// declarator chunks.
6867+
if (D.isDecompositionDeclarator())
6868+
return;
6869+
68656870
// If the declarator was parenthesized, we entered the declarator
68666871
// scope when parsing the parenthesized declarator, then exited
68676872
// the scope already. Re-enter the scope, if we need to.

clang/test/Parser/GH218144.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -std=c++26 -fsyntax-only -verify %s
3+
4+
b;([c,ac])(){}
5+
// expected-error@-1 2 {{a type specifier is required for all declarations}}
6+
// expected-error@-2 {{structured binding declaration cannot be declared with parentheses}}
7+
// expected-error@-3 {{expected expression}}
8+
// expected-error@-4 {{expected ';' after top level declarator}}
9+
10+
([d])(){d}
11+
// expected-error@-1 {{a type specifier is required for all declarations}}
12+
// expected-error@-2 {{structured binding declaration cannot be declared with parentheses}}
13+
// expected-error@-3 {{expected expression}}
14+
// expected-error@-4 {{expected ';' after top level declarator}}
15+
16+
auto ([a])() {}
17+
// expected-error@-1 {{structured binding declaration cannot be declared with parentheses}}
18+
// expected-error@-2 {{expected expression}}
19+
// expected-error@-3 {{expected ';' after top level declarator}}
20+
21+
auto (([x, y, z]))() {}
22+
// expected-error@-1 {{structured binding declaration cannot be declared with parentheses}}
23+
// expected-error@-2 {{expected expression}}
24+
// expected-error@-3 {{expected ';' after top level declarator}}
25+
26+
struct S {
27+
([m, n])() {}
28+
// expected-error@-1 {{structured binding declaration not permitted in this context}}
29+
// expected-error@-2 {{expected ';' at end of declaration list}}
30+
};

0 commit comments

Comments
 (0)