Message ID | 20240625010015.122204-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: decltype of by-ref capture proxy of ref [PR115504] | expand |
On 6/24/24 21:00, Patrick Palka wrote: > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > for trunk/14? > > -- >8 -- > > The capture proxy handling in finish_decltype_type added in r14-5330 > was stripping the reference type of a capture proxy's captured variable, > which is desirable for a by-value capture, but not for a by-ref capture > (of a reference). I'm not sure why we would want it for by-value, either; regardless of the capture kind, decltype(x) is int&. > PR c++/115504 > > gcc/cp/ChangeLog: > > * semantics.cc (finish_decltype_type): For a by-reference > capture proxy, don't strip the reference type (if any) of > the captured variable. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1y/decltype-auto8.C: New test. > --- > gcc/cp/semantics.cc | 4 +++- > gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 11 +++++++++++ > 2 files changed, 14 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index 08f5f245e7d..b4f626924af 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -12076,9 +12076,11 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, > { > if (is_normal_capture_proxy (expr)) > { > + bool by_ref = TYPE_REF_P (TREE_TYPE (expr)); > expr = DECL_CAPTURED_VARIABLE (expr); > type = TREE_TYPE (expr); > - type = non_reference (type); > + if (!by_ref) > + type = non_reference (type); > } > else > { > diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > new file mode 100644 > index 00000000000..9a5e435f14f > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > @@ -0,0 +1,11 @@ > +// PR c++/115504 > +// { dg-do compile { target c++14 } } > + > +void f(int& x) { > + [&x]() { > + decltype(auto) a = x; > + using type = decltype(x); > + using type = decltype(a); > + using type = int&; // not 'int' > + }; > +}
On Mon, 24 Jun 2024, Jason Merrill wrote: > On 6/24/24 21:00, Patrick Palka wrote: > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > > for trunk/14? > > > > -- >8 -- > > > > The capture proxy handling in finish_decltype_type added in r14-5330 > > was stripping the reference type of a capture proxy's captured variable, > > which is desirable for a by-value capture, but not for a by-ref capture > > (of a reference). > > I'm not sure why we would want it for by-value, either; regardless of the > capture kind, decltype(x) is int&. Ah, makes sense. But I guess that means void f(int& x) { [x]() { decltype(auto) a = x; } } is ill-formed since decltype(x) is int& but the corresponding closure member is const? It works if we make the lambda mutable. Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- Subject: [PATCH] c++: decltype of capture proxy of ref [PR115504] The capture proxy handling in finish_decltype_type added in r14-5330 was stripping the reference type of a capture proxy's captured variable. PR c++/115504 gcc/cp/ChangeLog: * semantics.cc (finish_decltype_type): Don't strip the reference type (if any) of a capture proxy's captured variable. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/decltype-auto8.C: New test. --- gcc/cp/semantics.cc | 1 - gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 6c1813d37c6..6a383c0f7f9 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12071,7 +12071,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, { expr = DECL_CAPTURED_VARIABLE (expr); type = TREE_TYPE (expr); - type = non_reference (type); } else { diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C new file mode 100644 index 00000000000..1100b94a5b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C @@ -0,0 +1,18 @@ +// PR c++/115504 +// { dg-do compile { target c++14 } } + +void f(int& x) { + [&x]() { + decltype(auto) a = x; + using type = decltype(x); + using type = decltype(a); + using type = int&; // not 'int' + }; + + [x]() mutable { + decltype(auto) a = x; + using type = decltype(x); + using type = decltype(a); + using type = int&; + }; +}
On 6/25/24 11:03, Patrick Palka wrote: > On Mon, 24 Jun 2024, Jason Merrill wrote: > >> On 6/24/24 21:00, Patrick Palka wrote: >>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK >>> for trunk/14? >>> >>> -- >8 -- >>> >>> The capture proxy handling in finish_decltype_type added in r14-5330 >>> was stripping the reference type of a capture proxy's captured variable, >>> which is desirable for a by-value capture, but not for a by-ref capture >>> (of a reference). >> >> I'm not sure why we would want it for by-value, either; regardless of the >> capture kind, decltype(x) is int&. > > Ah, makes sense. But I guess that means > > void f(int& x) { > [x]() { > decltype(auto) a = x; > } > } > > is ill-formed since decltype(x) is int& but the corresponding closure > member is const? It works if we make the lambda mutable. Yes, and clang agrees. Let's also test that case. > Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. > > > -- >8 -- > > Subject: [PATCH] c++: decltype of capture proxy of ref [PR115504] > > The capture proxy handling in finish_decltype_type added in r14-5330 > was stripping the reference type of a capture proxy's captured variable. > > PR c++/115504 > > gcc/cp/ChangeLog: > > * semantics.cc (finish_decltype_type): Don't strip the reference > type (if any) of a capture proxy's captured variable. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1y/decltype-auto8.C: New test. > --- > gcc/cp/semantics.cc | 1 - > gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 18 ++++++++++++++++++ > 2 files changed, 18 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index 6c1813d37c6..6a383c0f7f9 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -12071,7 +12071,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, > { > expr = DECL_CAPTURED_VARIABLE (expr); > type = TREE_TYPE (expr); > - type = non_reference (type); > } > else > { > diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > new file mode 100644 > index 00000000000..1100b94a5b7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > @@ -0,0 +1,18 @@ > +// PR c++/115504 > +// { dg-do compile { target c++14 } } > + > +void f(int& x) { > + [&x]() { > + decltype(auto) a = x; > + using type = decltype(x); > + using type = decltype(a); > + using type = int&; // not 'int' > + }; > + > + [x]() mutable { > + decltype(auto) a = x; > + using type = decltype(x); > + using type = decltype(a); > + using type = int&; > + }; > +}
On Tue, 25 Jun 2024, Jason Merrill wrote: > On 6/25/24 11:03, Patrick Palka wrote: > > On Mon, 24 Jun 2024, Jason Merrill wrote: > > > > > On 6/24/24 21:00, Patrick Palka wrote: > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > > > > for trunk/14? > > > > > > > > -- >8 -- > > > > > > > > The capture proxy handling in finish_decltype_type added in r14-5330 > > > > was stripping the reference type of a capture proxy's captured variable, > > > > which is desirable for a by-value capture, but not for a by-ref capture > > > > (of a reference). > > > > > > I'm not sure why we would want it for by-value, either; regardless of the > > > capture kind, decltype(x) is int&. > > > > Ah, makes sense. But I guess that means > > > > void f(int& x) { > > [x]() { > > decltype(auto) a = x; > > } > > } > > > > is ill-formed since decltype(x) is int& but the corresponding closure > > member is const? It works if we make the lambda mutable. > > Yes, and clang agrees. Let's also test that case. Like so? -- >8 -- Subject: [PATCH] c++: decltype of capture proxy of ref [PR115504] The capture proxy handling in finish_decltype_type added in r14-5330 was stripping the reference type of a capture proxy's captured variable. PR c++/115504 gcc/cp/ChangeLog: * semantics.cc (finish_decltype_type): Don't strip the reference type (if any) of a capture proxy's captured variable. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/decltype-auto8.C: New test. --- gcc/cp/semantics.cc | 1 - gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 22 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 6c1813d37c6..6a383c0f7f9 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12071,7 +12071,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, { expr = DECL_CAPTURED_VARIABLE (expr); type = TREE_TYPE (expr); - type = non_reference (type); } else { diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C new file mode 100644 index 00000000000..55135cecf72 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C @@ -0,0 +1,22 @@ +// PR c++/115504 +// { dg-do compile { target c++14 } } + +void f(int& x, const int& y) { + [&x]() { + decltype(auto) a = x; + using type = decltype(x); + using type = decltype(a); + using type = int&; // not 'int' + }; + + [x]() { + decltype(auto) a = x; // { dg-error "discards qualifiers" } + }; + + [x]() mutable { + decltype(auto) a = x; + using type = decltype(x); + using type = decltype(a); + using type = int&; + }; +}
On 6/25/24 11:45, Patrick Palka wrote: > On Tue, 25 Jun 2024, Jason Merrill wrote: > >> On 6/25/24 11:03, Patrick Palka wrote: >>> On Mon, 24 Jun 2024, Jason Merrill wrote: >>> >>>> On 6/24/24 21:00, Patrick Palka wrote: >>>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK >>>>> for trunk/14? >>>>> >>>>> -- >8 -- >>>>> >>>>> The capture proxy handling in finish_decltype_type added in r14-5330 >>>>> was stripping the reference type of a capture proxy's captured variable, >>>>> which is desirable for a by-value capture, but not for a by-ref capture >>>>> (of a reference). >>>> >>>> I'm not sure why we would want it for by-value, either; regardless of the >>>> capture kind, decltype(x) is int&. >>> >>> Ah, makes sense. But I guess that means >>> >>> void f(int& x) { >>> [x]() { >>> decltype(auto) a = x; >>> } >>> } >>> >>> is ill-formed since decltype(x) is int& but the corresponding closure >>> member is const? It works if we make the lambda mutable. >> >> Yes, and clang agrees. Let's also test that case. > > Like so? OK. > -- >8 -- > > Subject: [PATCH] c++: decltype of capture proxy of ref [PR115504] > > The capture proxy handling in finish_decltype_type added in r14-5330 > was stripping the reference type of a capture proxy's captured variable. > > PR c++/115504 > > gcc/cp/ChangeLog: > > * semantics.cc (finish_decltype_type): Don't strip the reference > type (if any) of a capture proxy's captured variable. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1y/decltype-auto8.C: New test. > --- > gcc/cp/semantics.cc | 1 - > gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C | 22 +++++++++++++++++++++ > 2 files changed, 22 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index 6c1813d37c6..6a383c0f7f9 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -12071,7 +12071,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, > { > expr = DECL_CAPTURED_VARIABLE (expr); > type = TREE_TYPE (expr); > - type = non_reference (type); > } > else > { > diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > new file mode 100644 > index 00000000000..55135cecf72 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C > @@ -0,0 +1,22 @@ > +// PR c++/115504 > +// { dg-do compile { target c++14 } } > + > +void f(int& x, const int& y) { > + [&x]() { > + decltype(auto) a = x; > + using type = decltype(x); > + using type = decltype(a); > + using type = int&; // not 'int' > + }; > + > + [x]() { > + decltype(auto) a = x; // { dg-error "discards qualifiers" } > + }; > + > + [x]() mutable { > + decltype(auto) a = x; > + using type = decltype(x); > + using type = decltype(a); > + using type = int&; > + }; > +}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 08f5f245e7d..b4f626924af 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12076,9 +12076,11 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, { if (is_normal_capture_proxy (expr)) { + bool by_ref = TYPE_REF_P (TREE_TYPE (expr)); expr = DECL_CAPTURED_VARIABLE (expr); type = TREE_TYPE (expr); - type = non_reference (type); + if (!by_ref) + type = non_reference (type); } else { diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C new file mode 100644 index 00000000000..9a5e435f14f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto8.C @@ -0,0 +1,11 @@ +// PR c++/115504 +// { dg-do compile { target c++14 } } + +void f(int& x) { + [&x]() { + decltype(auto) a = x; + using type = decltype(x); + using type = decltype(a); + using type = int&; // not 'int' + }; +}