On Thu, Nov 07, 2024 at 09:48:52PM +1100, Nathaniel Shead wrote: > Bootstrapped and lightly regtested on x86_64-pc-linux-gnu (so far just > dg.exp), OK for trunk if full regtest succeeds? > > -- >8 -- > > Decomposition of lambda closure types is not allowed by > [dcl.struct.bind] p6, since members of a closure have no name. > > r244909 made this an error, but missed the case where a lambda is used > as a base. This patch moves the check to find_decomp_class_base to > handle this case. > > As a drive-by improvement, we also slightly improve the diagnostics to > indicate why a base class was being inspected. Ideally the diagnostic > would point directly at the relevant base, but there doesn't seem to be > an easy way to get this location just from the binfo so I don't worry > about that here. > > PR c++/90321 > > gcc/cp/ChangeLog: > > * decl.cc (find_decomp_class_base): Check for decomposing a > lambda closure type. Report base class chains if needed. > (cp_finish_decomp): Remove no-longer-needed check. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1z/decomp62.C: New test. > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > --- > gcc/cp/decl.cc | 20 ++++++++++++++------ > gcc/testsuite/g++.dg/cpp1z/decomp62.C | 12 ++++++++++++ > 2 files changed, 26 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp62.C > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > index 0e4533c6fab..87480dca1ac 100644 > --- a/gcc/cp/decl.cc > +++ b/gcc/cp/decl.cc > @@ -9268,6 +9268,14 @@ cp_finish_decl (tree decl, tree init, bool > init_const_expr_p, > static tree > find_decomp_class_base (location_t loc, tree type, tree ret) > { > + if (LAMBDA_TYPE_P (type)) > + {
Missing auto_diagnostic_group d; here? > + error_at (loc, "cannot decompose lambda closure type %qT", type); > + inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), > + "lambda declared here"); > + return error_mark_node; > + } > + > bool member_seen = false; > for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) > if (TREE_CODE (field) != FIELD_DECL > @@ -9310,9 +9318,14 @@ find_decomp_class_base (location_t loc, tree type, > tree ret) > for (binfo = TYPE_BINFO (type), i = 0; > BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) > { > + auto_diagnostic_group d; > tree t = find_decomp_class_base (loc, TREE_TYPE (base_binfo), ret); > if (t == error_mark_node) > - return error_mark_node; > + { > + inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), location_of might be nicer. Otherwise looks fine to me, thanks! > + "in base class of %qT", type); > + return error_mark_node; > + } > if (t != NULL_TREE && t != ret) > { > if (ret == type) > @@ -9768,11 +9781,6 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool > test_p) > error_at (loc, "cannot decompose non-array non-class type %qT", type); > goto error_out; > } > - else if (LAMBDA_TYPE_P (type)) > - { > - error_at (loc, "cannot decompose lambda closure type %qT", type); > - goto error_out; > - } > else if (processing_template_decl && complete_type (type) == > error_mark_node) > goto error_out; > else if (processing_template_decl && !COMPLETE_TYPE_P (type)) > diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp62.C > b/gcc/testsuite/g++.dg/cpp1z/decomp62.C > new file mode 100644 > index 00000000000..b0ce10570c7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1z/decomp62.C > @@ -0,0 +1,12 @@ > +// PR c++/90321 > +// { dg-do compile { target c++17 } } > + > +template<class F> struct hack : F { }; > +template<class F> hack(F) -> hack<F>; > + > +int main() > +{ > + auto f = [x = 1, y = 2]() { }; > + auto [a, b] = hack { f }; // { dg-error "cannot decompose lambda > closure type" } > + return b; > +} > -- > 2.47.0 > Marek