public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: decltype of (by-value captured reference) [PR79620]
@ 2023-11-07 19:52 Patrick Palka
  2023-11-07 19:55 ` Patrick Palka
  2023-11-10  0:32 ` Jason Merrill
  0 siblings, 2 replies; 3+ messages in thread
From: Patrick Palka @ 2023-11-07 19:52 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Patrick Palka

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.

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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] c++: decltype of (by-value captured reference) [PR79620]
  2023-11-07 19:52 [PATCH] c++: decltype of (by-value captured reference) [PR79620] Patrick Palka
@ 2023-11-07 19:55 ` Patrick Palka
  2023-11-10  0:32 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Patrick Palka @ 2023-11-07 19:55 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, jason

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
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] c++: decltype of (by-value captured reference) [PR79620]
  2023-11-07 19:52 [PATCH] c++: decltype of (by-value captured reference) [PR79620] Patrick Palka
  2023-11-07 19:55 ` Patrick Palka
@ 2023-11-10  0:32 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2023-11-10  0:32 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

On 11/7/23 14:52, 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.
> 
> 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))

Let's also have outer_automatic_var_p assert that its argument is not 
REFERENCE_REF_P.  OK with that change (if no regressions).

Jason


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-11-10  0:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-07 19:52 [PATCH] c++: decltype of (by-value captured reference) [PR79620] Patrick Palka
2023-11-07 19:55 ` Patrick Palka
2023-11-10  0:32 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).