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 <[email protected]>
> ---
> 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