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

Reply via email to