On Tue, 7 Nov 2023, Patrick Palka wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?
> 
> -- >8 --
> 
> The capture decltype handling in finish_decltype_type wasn't looking
> through implicit INDIRECT_REF (added by convert_from_reference), which
> caused us to incorrectly resolve decltype((x)) to float& below.

Oops, this should say decltype((r)).  We already correctly resolve
decltype((x)) to const float& (since x isn't a reference).

> 
> We still don't fully accept the example ultimately because when
> processing the decltype inside the first lambda's trailing return type,
> we're in lambda type scope but not yet in lambda function scope that
> the check looks for, which seems like an orthogonal bug.
> 
>       PR c++/79620
> 
> gcc/cp/ChangeLog:
> 
>       * cp-tree.h (STRIP_REFERENCE_REF): Define.
>       * semantics.cc (finish_decltype_type): Use it to look
>       through implicit INDIRECT_REF when deciding whether to
>       call capture_decltype.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/cpp0x/lambda/lambda-decltype3.C: New test.
> ---
>  gcc/cp/cp-tree.h                              |  4 +++
>  gcc/cp/semantics.cc                           |  4 +--
>  .../g++.dg/cpp0x/lambda/lambda-decltype3.C    | 28 +++++++++++++++++++
>  3 files changed, 34 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype3.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index b2603d4830e..1fa710d7154 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -4084,6 +4084,10 @@ struct GTY(()) lang_decl {
>     && TREE_TYPE (TREE_OPERAND (NODE, 0))             \
>     && TYPE_REF_P (TREE_TYPE (TREE_OPERAND ((NODE), 0))))
>  
> +/* Look through an implicit INDIRECT_REF from convert_from_reference.  */
> +#define STRIP_REFERENCE_REF(NODE)                    \
> +  (REFERENCE_REF_P (NODE) ? TREE_OPERAND (NODE, 0) : NODE)
> +
>  /* True iff this represents an lvalue being treated as an rvalue during 
> return
>     or throw as per [class.copy.elision].  */
>  #define IMPLICIT_RVALUE_P(NODE) \
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index f583dedd6cf..8df4521bf7c 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -11717,10 +11717,10 @@ finish_decltype_type (tree expr, bool 
> id_expression_or_member_access_p,
>        transformed into an access to a corresponding data member
>        of the closure type that would have been declared if x
>        were a use of the denoted entity.  */
> -      if (outer_automatic_var_p (expr)
> +      if (outer_automatic_var_p (STRIP_REFERENCE_REF (expr))
>         && current_function_decl
>         && LAMBDA_FUNCTION_P (current_function_decl))
> -     type = capture_decltype (expr);
> +     type = capture_decltype (STRIP_REFERENCE_REF (expr));
>        else if (error_operand_p (expr))
>       type = error_mark_node;
>        else if (expr == current_class_ptr)
> diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype3.C 
> b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype3.C
> new file mode 100644
> index 00000000000..7fc157aefb5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype3.C
> @@ -0,0 +1,28 @@
> +// PR c++/79620
> +// [expr.prim.id.unqual] example 1
> +// { dg-do compile { target c++11 } }
> +
> +void f() {
> +  float x, &r = x;
> +
> +  [=]() -> decltype((x)) {      // lambda returns float const& because this 
> lambda is not mutable and
> +                                // x is an lvalue
> +    decltype(x) y1;             // y1 has type float
> +    decltype((x)) y2 = y1;      // y2 has type float const&
> +    decltype(r) r1 = y1;        // r1 has type float&
> +    decltype((r)) r2 = y2;      // r2 has type float const&
> +    return y2;                  // { dg-bogus "'float&' to 'const float'" "" 
> { xfail *-*-* } }
> +  };
> +
> +  [=](decltype((x)) y) {
> +    decltype((x)) z = x;        // OK, y has type float&, z has type float 
> const&
> +  };
> +
> +  [=] {
> +    [](decltype((x)) y) {};     // OK, lambda takes a parameter of type 
> float const&
> +
> +    [x=1](decltype((x)) y) {
> +      decltype((x)) z = x;      // OK, y has type int&, z has type int const&
> +    };
> +  };
> +}
> -- 
> 2.43.0.rc0.23.g8be77c5de6
> 
> 

Reply via email to