c++: Detect unexpandable packs based on scope #213

Open
feedable wants to merge 1 commit from feedable/gcc-TEST:pr126124 into trunk
Member

This patch rewrites old unexpandable pack detection logic based on
current lambda to a one based on scopes.

The new logic tries to answer the following question: "Will the soonest
potential pack expansion have a pack that is declared within its own
pattern?". There aren't a lot of scopes over which we can directly
expand (only lambda and stmt-expr). We can take advantage of that and
assert that any expansion that hasn't occured yet must occur beyond that
scope, so any pack that's declared within that scope, cannot be expanded
over, as it would be within the pattern itself.
For example:

struct X { int x,y,z; };
template<class ...T>
void foo() {
([]{auto [...xs] = X{}; xs + T{};}, ...);
}
When check_for_bare_parameter_packs is called for the expr-stmt
xs + T{};, any possible expansion over that pack will contain the
lambda-scope, and as xs is declared within that scope, it will also be
contained within the pattern of that expansion, while T is declared
outside of that scope, so there are expansions which can expand it
without containing its declaration within the pattern.

Also, do actually check for bare parameter packs in the final statement
of a stmt-expr.

PR c++/126124

gcc/cp/ChangeLog:

* pt.cc (nearest_expandable_scope): New.
(filter_packs): New.
(check_for_bare_parameter_packs): Use scopes for bare pack
detection.
* semantics.cc (finish_stmt_expr_expr): Check for bare packs.
(finish_member_declaration): Skip for lambda fields.

gcc/testsuite/ChangeLog:

* g++.dg/cpp26/decomp33.C: New test.
* g++.dg/cpp2a/lambda-generic-variadic-22.C: New test.
* g++.dg/expr/stmt-expr-2.C: New test.

Changes since v1:

  • Removed constexpr from the variable for the lambda in
    filter_packs.

Changes since v2:

  • Rephrased the comment in finish_stmt_expr_expr.
  • Skipped bare param pack check for lambda fields.
  • Tweaked loop in filter_packs.

CC: jason@redhat.com

This patch rewrites old unexpandable pack detection logic based on current lambda to a one based on scopes. The new logic tries to answer the following question: "Will the soonest potential pack expansion have a pack that is declared within its own pattern?". There aren't a lot of scopes over which we can directly expand (only lambda and stmt-expr). We can take advantage of that and assert that any expansion that hasn't occured yet must occur beyond that scope, so any pack that's declared within that scope, cannot be expanded over, as it would be within the pattern itself. For example: struct X { int x,y,z; }; template<class ...T> void foo() { ([]{auto [...xs] = X{}; xs + T{};}, ...); } When `check_for_bare_parameter_packs` is called for the expr-stmt `xs + T{};`, any possible expansion over that pack will contain the lambda-scope, and as `xs` is declared within that scope, it will also be contained within the pattern of that expansion, while `T` is declared outside of that scope, so there are expansions which can expand it without containing its declaration within the pattern. Also, do actually check for bare parameter packs in the final statement of a stmt-expr. PR c++/126124 gcc/cp/ChangeLog: * pt.cc (nearest_expandable_scope): New. (filter_packs): New. (check_for_bare_parameter_packs): Use scopes for bare pack detection. * semantics.cc (finish_stmt_expr_expr): Check for bare packs. (finish_member_declaration): Skip for lambda fields. gcc/testsuite/ChangeLog: * g++.dg/cpp26/decomp33.C: New test. * g++.dg/cpp2a/lambda-generic-variadic-22.C: New test. * g++.dg/expr/stmt-expr-2.C: New test. Changes since v1: - Removed `constexpr` from the variable for the lambda in `filter_packs`. Changes since v2: - Rephrased the comment in `finish_stmt_expr_expr`. - Skipped bare param pack check for lambda fields. - Tweaked loop in `filter_packs`. CC: jason@redhat.com
Member

Hi @feedable. This bot helps send your PR as a patch series to the mailing list.

Next steps

  1. Write a clear PR description. It will be used as the cover letter.
  2. To CC extra people, add lines like this at the end of the PR description: CC: Reviewer1 <revi.ewer@example.com>, Reviewer2 <an.other@example.com>.
  3. To preview the emails, comment with /preview.
  4. When ready, request review in the Reviewers section. Or, if you just want to send the series, comment with /submit.
  5. Use the cover-letter links below to follow replies.
  6. For a new patch series, push your changes, update the PR description with a Changes since vX section, and comment with /submit again.

See Submitting Patches and UsingForge.

Consider joining the gcc and gcc-patches mailing lists..
For real time communication, check the gcc irc channels.

Or join #overseers on Libera Chat, particularly if this automation is not working (stay online to get replies, IRC does not save messages if people are not online).

<!-- pr-welcome --> Hi @feedable. This bot helps send your PR as a patch series to the mailing list. ## Next steps 1. Write a clear PR description. It will be used as the cover letter. 2. To CC extra people, add lines like this **at the end** of the PR description: `CC: Reviewer1 <revi.ewer@example.com>, Reviewer2 <an.other@example.com>`. 3. To preview the emails, comment with `/preview`. 4. When ready, request review in the Reviewers section. Or, if you just want to send the series, comment with `/submit`. 5. Use the cover-letter links below to follow replies. 6. For a new patch series, push your changes, update the PR description with a `Changes since vX` section, and comment with `/submit` again. See [Submitting Patches](https://gcc.gnu.org/contribute.html#patches) and [UsingForge](https://gcc.gnu.org/wiki/UsingForge). Consider joining the [gcc and gcc-patches mailing lists.](https://gcc.gnu.org/lists.html). For real time communication, check the [gcc irc channels](https://gcc.gnu.org/wiki/GCConIRC). Or join [`#overseers`](https://web.libera.chat/#overseers) on Libera Chat, particularly if this automation is not working (stay online to get replies, IRC does not save messages if people are not online).
feedable force-pushed pr126124 from cdd9210f98
Some checks failed
/ format-checks (pull_request) Failing after 1m34s
to 921687aa8a
Some checks failed
/ format-checks (pull_request) Failing after 1m29s
2026-08-08 16:46:42 +00:00
Compare
Author
Member

/preview

/preview
Member

Sent patch version 1 as a single email to @feedable's email address.
Message ID is <bmm.hl5olwsvrg.gcc.gcc.feedable.213.1.0@forge-stage.sourceware.org>.

Sent patch version 1 as a single email to @feedable's email address. Message ID is `<bmm.hl5olwsvrg.gcc.gcc.feedable.213.1.0@forge-stage.sourceware.org>`.
feedable force-pushed pr126124 from 921687aa8a
Some checks failed
/ format-checks (pull_request) Failing after 1m29s
to 86e7fd6fbf
All checks were successful
/ format-checks (pull_request) Successful in 1m32s
2026-08-08 17:00:25 +00:00
Compare
Author
Member

/submit

/submit
Member

Version 1 of this pull request has been stored. It includes the following commits:

  • c++: Detect unexpandable packs based on scope - 86e7fd6fbf
<!-- pr-new-version --> Version 1 of this pull request has been stored. It includes the following commits: - c++: Detect unexpandable packs based on scope - 86e7fd6fbf53a7ae8fc2643f8bf870041bf76332
Member

Sent patch version 1 as a single email to gcc-patches mailing list gcc-patches@gcc.gnu.org.
Cover letter

Sent patch version 1 as a single email to gcc-patches mailing list <gcc-patches@gcc.gnu.org>. [Cover letter](https://inbox.sourceware.org/gcc-patches/bmm.hl5ovh7dlc.gcc.gcc.feedable.213.1.0@forge-stage.sourceware.org)
feedable force-pushed pr126124 from 86e7fd6fbf
All checks were successful
/ format-checks (pull_request) Successful in 1m32s
to 66cadb90dd
All checks were successful
/ format-checks (pull_request) Successful in 1m35s
2026-08-10 14:01:04 +00:00
Compare
Author
Member

/submit

/submit
Member

Version 2 of this pull request has been stored. It includes the following commits:

  • c++: Detect unexpandable packs based on scope - 66cadb90dd
<!-- pr-new-version --> Version 2 of this pull request has been stored. It includes the following commits: - c++: Detect unexpandable packs based on scope - 66cadb90dd11330a04d1801f1a3597eba719129f
Member

Sent patch version 2 as a single email to gcc-patches mailing list gcc-patches@gcc.gnu.org and cc'd jason@redhat.com.
Cover letter

Sent patch version 2 as a single email to gcc-patches mailing list <gcc-patches@gcc.gnu.org> and cc'd jason@redhat.com. [Cover letter](https://inbox.sourceware.org/gcc-patches/bmm.hl7tplunqo.gcc.gcc.feedable.213.2.0@forge-stage.sourceware.org)
feedable force-pushed pr126124 from 66cadb90dd
All checks were successful
/ format-checks (pull_request) Successful in 1m35s
to 56c40064a0
All checks were successful
/ format-checks (pull_request) Successful in 1m22s
2026-10-06 16:06:39 +00:00
Compare
Author
Member

/submit

/submit
Member

Version 3 of this pull request has been stored. It includes the following commits:

  • c++: Detect unexpandable packs based on scope - 56c40064a0
<!-- pr-new-version --> Version 3 of this pull request has been stored. It includes the following commits: - c++: Detect unexpandable packs based on scope - 56c40064a048cf2a1eb379f9b0cabbd36241ceb8
Member

Pull Request versions:

# Base Head
1 31f66a8434 86e7fd6fbf (diff)
2 2791799fe1 66cadb90dd (diff)
3 8a312e7a44 56c40064a0 (diff)

In order to compare , clone this repository and run

PR=213
git fetch origin "refs/versioned_pull/${PR}/*:refs/versioned_pull/${PR}/*"
PRV1=1
PRV2=2
git range-diff "refs/versioned_pull/${PR}/${PRV1}/base..refs/versioned_pull/${PR}/${PRV1}/head"  "refs/versioned_pull/${PR}/${PRV2}/base..refs/versioned_pull/${PR}/${PRV2}/head"
<!-- pr-versions --> Pull Request versions: | # | Base | Head | | | - | ---- | ---- | - | | 1 | 31f66a843429269ee9cdc6ce69ba3ff698773a35 | 86e7fd6fbf53a7ae8fc2643f8bf870041bf76332 | [(diff)](https://forge.sourceware.org/gcc/gcc.git/compare/31f66a843429269ee9cdc6ce69ba3ff698773a35...86e7fd6fbf53a7ae8fc2643f8bf870041bf76332) | | 2 | 2791799fe11f886736869e3aff093e0c14fb10b8 | 66cadb90dd11330a04d1801f1a3597eba719129f | [(diff)](https://forge.sourceware.org/gcc/gcc.git/compare/2791799fe11f886736869e3aff093e0c14fb10b8...66cadb90dd11330a04d1801f1a3597eba719129f) | | 3 | 8a312e7a448a81d5447729c2743ec7b69b581402 | 56c40064a048cf2a1eb379f9b0cabbd36241ceb8 | [(diff)](https://forge.sourceware.org/gcc/gcc.git/compare/8a312e7a448a81d5447729c2743ec7b69b581402...56c40064a048cf2a1eb379f9b0cabbd36241ceb8) | In order to compare , clone this repository and run ``` PR=213 git fetch origin "refs/versioned_pull/${PR}/*:refs/versioned_pull/${PR}/*" PRV1=1 PRV2=2 git range-diff "refs/versioned_pull/${PR}/${PRV1}/base..refs/versioned_pull/${PR}/${PRV1}/head" "refs/versioned_pull/${PR}/${PRV2}/base..refs/versioned_pull/${PR}/${PRV2}/head" ```
Member

Sent patch version 3 as a single email to gcc-patches mailing list gcc-patches@gcc.gnu.org and cc'd jason@redhat.com.
Cover letter

Sent patch version 3 as a single email to gcc-patches mailing list <gcc-patches@gcc.gnu.org> and cc'd jason@redhat.com. [Cover letter](https://inbox.sourceware.org/gcc-patches/bmm.hmypcfr7fc.gcc.gcc.feedable.213.3.0@forge-stage.sourceware.org)
All checks were successful
/ format-checks (pull_request) Successful in 1m22s
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u pr126124:feedable-pr126124
git switch feedable-pr126124

Merge

Merge the changes and update on Forgejo.
git switch trunk
git merge --no-ff feedable-pr126124
git switch feedable-pr126124
git rebase trunk
git switch trunk
git merge --ff-only feedable-pr126124
git switch feedable-pr126124
git rebase trunk
git switch trunk
git merge --no-ff feedable-pr126124
git switch trunk
git merge --squash feedable-pr126124
git switch trunk
git merge --ff-only feedable-pr126124
git switch trunk
git merge feedable-pr126124
git push origin trunk
Sign in to join this conversation.
No reviewers
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gcc/gcc!213
No description provided.