Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Jason Merrill via Gcc-patches

On 3/16/23 11:48, Patrick Palka wrote:

On Thu, 16 Mar 2023, Jason Merrill wrote:


On 3/16/23 10:09, Patrick Palka wrote:

On Wed, 15 Mar 2023, Patrick Palka wrote:


On Thu, 9 Mar 2023, Jason Merrill wrote:


On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided:
build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
gcc/cp/constexpr.cc | 6 +-
gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx
*ctx,
tree t,
/* We used to shortcut trivial constructor/op= here, but
nowadays
 we can only get a trivial function here with
-fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) ||
!flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second
way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in
maybe_constant_value?


Sounds good.


Hmm, while working on this I noticed we currently don't reject a version
of
g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead
of
int (ever since r12-4425-g1595fe44e11a96):

struct A { int m; };
template constexpr int f() { return T::value; }
template void h(decltype(A{B ? f() : 0})); //
was int{...}
template void h(...);
void x() {
  h(0); // OK?
}

ISTM we should instantiate f here for the same reason we do in the
original version of the testcase, and for that to happen we need to
pass manifestly_const_eval=true in massage_init_elt.  Does that seem
reasonable?



FWIW the reason this came up is because I tried contriving a testcase
for the aforementioned maybe_constant_init change, and I came up with:

struct __as_receiver {
  int empty_env;
};

template
constexpr int f(T t) {
  return t.fail;
};

using type = decltype(__as_receiver{f(0)}); // OK, f no longer
instantiated

which we used to reject and afterwards accept.  But since the elements
of an initializer list are potentially constant evaluated, I wonder if
that that means f should be instantiated here after all despite the
unevaluated context?


The relevant section of the standard would seem to be
https://eel.is/c++draft/expr.const#20 ; an immediate subexpression of a
braced-init-list is potentially constant-evaluated even though it isn't
potentially-evaluated or manifestly constant-evaluated.

It seems like the call to fold_non_dependent_expr in check_narrowing ought to
cause instantiation in this case, why doesn't it?


Looks like check_narrowing isn't called at all in this aggr init case.
The call from e.g. convert_like_internal isn't reached because the
conversion for the initializer element is ck_identity, and don't ever
set conversion::check_narrowing for ck_identity conversions I think.


Ah, yes, that makes sense; an identity conversion can never be 
narrowing, so we don't care about the constant value.  So not 
instantiating seems correct, and the patch is OK.



Yet for using 'type = decltype(int{f(0)});' (similar to the example in
[temp.inst]/8) we do call check_narrowing directly from
finish_compound_literal, despite the conversion effectively being an
identity conversion.


Hmm, maybe check_narrowing should defer constant evaluation until after 
deciding that the target type is not a superset of the source type...



Here's the full patch for reference:

-- >8 --

Subject: [PATCH] c++: maybe_constant_init and unevaluated operands
[PR109030]

This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7)
illustrates that maybe_constant_init can be called on an unevaluated
operand (from massage_init_elt), so this entry point should limit
constant evaluation in that case, like maybe_constant_value does.

PR c++/10

Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Patrick Palka via Gcc-patches
On Thu, 16 Mar 2023, Jason Merrill wrote:

> On 3/16/23 10:09, Patrick Palka wrote:
> > On Wed, 15 Mar 2023, Patrick Palka wrote:
> > 
> > > On Thu, 9 Mar 2023, Jason Merrill wrote:
> > > 
> > > > On 3/9/23 14:32, Patrick Palka wrote:
> > > > > On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:
> > > > > 
> > > > > > When processing a noexcept, constructors aren't elided:
> > > > > > build_over_call
> > > > > > has
> > > > > >  /* It's unsafe to elide the constructor when handling
> > > > > > a noexcept-expression, it may evaluate to the wrong
> > > > > > value (c++/53025).  */
> > > > > >  && (force_elide || cp_noexcept_operand == 0))
> > > > > > so the assert I added recently needs to be relaxed a little bit.
> > > > > > 
> > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > > > 
> > > > > > PR c++/109030
> > > > > > 
> > > > > > gcc/cp/ChangeLog:
> > > > > > 
> > > > > > * constexpr.cc (cxx_eval_call_expression): Relax assert.
> > > > > > 
> > > > > > gcc/testsuite/ChangeLog:
> > > > > > 
> > > > > > * g++.dg/cpp0x/noexcept77.C: New test.
> > > > > > ---
> > > > > >gcc/cp/constexpr.cc | 6 +-
> > > > > >gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
> > > > > >2 files changed, 14 insertions(+), 1 deletion(-)
> > > > > >create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> > > > > > 
> > > > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > > > index 364695b762c..5384d0e8e46 100644
> > > > > > --- a/gcc/cp/constexpr.cc
> > > > > > +++ b/gcc/cp/constexpr.cc
> > > > > > @@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx
> > > > > > *ctx,
> > > > > > tree t,
> > > > > >/* We used to shortcut trivial constructor/op= here, but
> > > > > > nowadays
> > > > > > we can only get a trivial function here with
> > > > > > -fno-elide-constructors.  */
> > > > > > -  gcc_checking_assert (!trivial_fn_p (fun) ||
> > > > > > !flag_elide_constructors);
> > > > > > +  gcc_checking_assert (!trivial_fn_p (fun)
> > > > > > +  || !flag_elide_constructors
> > > > > > +  /* We don't elide constructors when processing
> > > > > > + a noexcept-expression.  */
> > > > > > +  || cp_noexcept_operand);
> > > > > 
> > > > > It seems weird that we're performing constant evaluation within an
> > > > > unevaluated operand.  Would it make sense to also fix this a second
> > > > > way
> > > > > by avoiding constant evaluation from maybe_constant_init when
> > > > > cp_unevaluated_operand && !manifestly_const_eval, like in
> > > > > maybe_constant_value?
> > > > 
> > > > Sounds good.
> > > 
> > > Hmm, while working on this I noticed we currently don't reject a version
> > > of
> > > g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead
> > > of
> > > int (ever since r12-4425-g1595fe44e11a96):
> > > 
> > >struct A { int m; };
> > >template constexpr int f() { return T::value; }
> > >template void h(decltype(A{B ? f() : 0})); //
> > > was int{...}
> > >template void h(...);
> > >void x() {
> > >  h(0); // OK?
> > >}
> > > 
> > > ISTM we should instantiate f here for the same reason we do in the
> > > original version of the testcase, and for that to happen we need to
> > > pass manifestly_const_eval=true in massage_init_elt.  Does that seem
> > > reasonable?
> > > 
> > 
> > FWIW the reason this came up is because I tried contriving a testcase
> > for the aforementioned maybe_constant_init change, and I came up with:
> > 
> >struct __as_receiver {
> >  int empty_env;
> >};
> > 
> >template
> >constexpr int f(T t) {
> >  return t.fail;
> >};
> > 
> >using type = decltype(__as_receiver{f(0)}); // OK, f no longer
> > instantiated
> > 
> > which we used to reject and afterwards accept.  But since the elements
> > of an initializer list are potentially constant evaluated, I wonder if
> > that that means f should be instantiated here after all despite the
> > unevaluated context?
> 
> The relevant section of the standard would seem to be
> https://eel.is/c++draft/expr.const#20 ; an immediate subexpression of a
> braced-init-list is potentially constant-evaluated even though it isn't
> potentially-evaluated or manifestly constant-evaluated.
> 
> It seems like the call to fold_non_dependent_expr in check_narrowing ought to
> cause instantiation in this case, why doesn't it?

Looks like check_narrowing isn't called at all in this aggr init case.
The call from e.g. convert_like_internal isn't reached because the
conversion for the initializer element is ck_identity, and don't ever
set conversion::check_narrowing for ck_identity conversions I think.

Yet for using 'type = decltype(int{f(0)});' (similar to the example in
[temp.inst]/8) we do call check_narrowing directly from
finish_compound_literal, despite the conversion effectively being 

Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Jason Merrill via Gcc-patches

On 3/16/23 10:09, Patrick Palka wrote:

On Wed, 15 Mar 2023, Patrick Palka wrote:


On Thu, 9 Mar 2023, Jason Merrill wrote:


On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
   gcc/cp/constexpr.cc | 6 +-
   gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
   2 files changed, 14 insertions(+), 1 deletion(-)
   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
tree t,
   /* We used to shortcut trivial constructor/op= here, but nowadays
we can only get a trivial function here with
-fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in
maybe_constant_value?


Sounds good.


Hmm, while working on this I noticed we currently don't reject a version of
g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead of
int (ever since r12-4425-g1595fe44e11a96):

   struct A { int m; };
   template constexpr int f() { return T::value; }
   template void h(decltype(A{B ? f() : 0})); // was 
int{...}
   template void h(...);
   void x() {
 h(0); // OK?
   }

ISTM we should instantiate f here for the same reason we do in the
original version of the testcase, and for that to happen we need to
pass manifestly_const_eval=true in massage_init_elt.  Does that seem
reasonable?



FWIW the reason this came up is because I tried contriving a testcase
for the aforementioned maybe_constant_init change, and I came up with:

   struct __as_receiver {
 int empty_env;
   };

   template
   constexpr int f(T t) {
 return t.fail;
   };

   using type = decltype(__as_receiver{f(0)}); // OK, f no longer 
instantiated

which we used to reject and afterwards accept.  But since the elements
of an initializer list are potentially constant evaluated, I wonder if
that that means f should be instantiated here after all despite the
unevaluated context?


The relevant section of the standard would seem to be
https://eel.is/c++draft/expr.const#20 ; an immediate subexpression of a 
braced-init-list is potentially constant-evaluated even though it isn't 
potentially-evaluated or manifestly constant-evaluated.


It seems like the call to fold_non_dependent_expr in check_narrowing 
ought to cause instantiation in this case, why doesn't it?



Here's the full patch for reference:

-- >8 --

Subject: [PATCH] c++: maybe_constant_init and unevaluated operands [PR109030]

This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7)
illustrates that maybe_constant_init can be called on an unevaluated
operand (from massage_init_elt), so this entry point should limit
constant evaluation in that case, like maybe_constant_value does.

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_init_1): For an unevaluated
non-manifestly-constant operand, don't constant evaluate
and instead call fold_to_constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype83.C: New test.
---
  gcc/cp/constexpr.cc |  2 ++
  gcc/testsuite/g++.dg/cpp0x/decltype83.C | 14 ++
  2 files changed, 16 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype83.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..f325af375c8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8795,6 +8795,8 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (is_static)
manifestly_const_eval = true;
+  if (cp_unevaluated_operand && !manifestly_const_eval)
+  

Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-16 Thread Patrick Palka via Gcc-patches
On Wed, 15 Mar 2023, Patrick Palka wrote:

> On Thu, 9 Mar 2023, Jason Merrill wrote:
> 
> > On 3/9/23 14:32, Patrick Palka wrote:
> > > On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:
> > > 
> > > > When processing a noexcept, constructors aren't elided: build_over_call
> > > > has
> > > >  /* It's unsafe to elide the constructor when handling
> > > > a noexcept-expression, it may evaluate to the wrong
> > > > value (c++/53025).  */
> > > >  && (force_elide || cp_noexcept_operand == 0))
> > > > so the assert I added recently needs to be relaxed a little bit.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > 
> > > > PR c++/109030
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constexpr.cc (cxx_eval_call_expression): Relax assert.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/cpp0x/noexcept77.C: New test.
> > > > ---
> > > >   gcc/cp/constexpr.cc | 6 +-
> > > >   gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
> > > >   2 files changed, 14 insertions(+), 1 deletion(-)
> > > >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> > > > 
> > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > > index 364695b762c..5384d0e8e46 100644
> > > > --- a/gcc/cp/constexpr.cc
> > > > +++ b/gcc/cp/constexpr.cc
> > > > @@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx 
> > > > *ctx,
> > > > tree t,
> > > >   /* We used to shortcut trivial constructor/op= here, but nowadays
> > > >we can only get a trivial function here with
> > > > -fno-elide-constructors.  */
> > > > -  gcc_checking_assert (!trivial_fn_p (fun) || 
> > > > !flag_elide_constructors);
> > > > +  gcc_checking_assert (!trivial_fn_p (fun)
> > > > +  || !flag_elide_constructors
> > > > +  /* We don't elide constructors when processing
> > > > + a noexcept-expression.  */
> > > > +  || cp_noexcept_operand);
> > > 
> > > It seems weird that we're performing constant evaluation within an
> > > unevaluated operand.  Would it make sense to also fix this a second way
> > > by avoiding constant evaluation from maybe_constant_init when
> > > cp_unevaluated_operand && !manifestly_const_eval, like in
> > > maybe_constant_value?
> > 
> > Sounds good.
> 
> Hmm, while working on this I noticed we currently don't reject a version of
> g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead of
> int (ever since r12-4425-g1595fe44e11a96):
> 
>   struct A { int m; };
>   template constexpr int f() { return T::value; }
>   template void h(decltype(A{B ? f() : 0})); // was 
> int{...}
>   template void h(...);
>   void x() {
> h(0); // OK?
>   }
> 
> ISTM we should instantiate f here for the same reason we do in the
> original version of the testcase, and for that to happen we need to
> pass manifestly_const_eval=true in massage_init_elt.  Does that seem
> reasonable?
> 

FWIW the reason this came up is because I tried contriving a testcase
for the aforementioned maybe_constant_init change, and I came up with:

  struct __as_receiver {
int empty_env;
  };

  template
  constexpr int f(T t) {
return t.fail;
  };

  using type = decltype(__as_receiver{f(0)}); // OK, f no longer 
instantiated

which we used to reject and afterwards accept.  But since the elements
of an initializer list are potentially constant evaluated, I wonder if
that that means f should be instantiated here after all despite the
unevaluated context?

Here's the full patch for reference:

-- >8 --

Subject: [PATCH] c++: maybe_constant_init and unevaluated operands [PR109030]

This testcase in this PR (already fixed by r13-6526-ge4692319fd5fc7)
illustrates that maybe_constant_init can be called on an unevaluated
operand (from massage_init_elt), so this entry point should limit
constant evaluation in that case, like maybe_constant_value does.

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_init_1): For an unevaluated
non-manifestly-constant operand, don't constant evaluate
and instead call fold_to_constant.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/decltype83.C: New test.
---
 gcc/cp/constexpr.cc |  2 ++
 gcc/testsuite/g++.dg/cpp0x/decltype83.C | 14 ++
 2 files changed, 16 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype83.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8683c00596a..f325af375c8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8795,6 +8795,8 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
   if (is_static)
manifestly_const_eval = true;
+  if (cp_unevaluated_operand && !manifestly_const_eval)
+   return fold_to_consta

Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-15 Thread Patrick Palka via Gcc-patches
On Thu, 9 Mar 2023, Jason Merrill wrote:

> On 3/9/23 14:32, Patrick Palka wrote:
> > On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:
> > 
> > > When processing a noexcept, constructors aren't elided: build_over_call
> > > has
> > >/* It's unsafe to elide the constructor when handling
> > >   a noexcept-expression, it may evaluate to the wrong
> > >   value (c++/53025).  */
> > >&& (force_elide || cp_noexcept_operand == 0))
> > > so the assert I added recently needs to be relaxed a little bit.
> > > 
> > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > 
> > >   PR c++/109030
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > >   * constexpr.cc (cxx_eval_call_expression): Relax assert.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > >   * g++.dg/cpp0x/noexcept77.C: New test.
> > > ---
> > >   gcc/cp/constexpr.cc | 6 +-
> > >   gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
> > >   2 files changed, 14 insertions(+), 1 deletion(-)
> > >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> > > 
> > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > > index 364695b762c..5384d0e8e46 100644
> > > --- a/gcc/cp/constexpr.cc
> > > +++ b/gcc/cp/constexpr.cc
> > > @@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
> > > tree t,
> > >   /* We used to shortcut trivial constructor/op= here, but nowadays
> > >we can only get a trivial function here with
> > > -fno-elide-constructors.  */
> > > -  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
> > > +  gcc_checking_assert (!trivial_fn_p (fun)
> > > +|| !flag_elide_constructors
> > > +/* We don't elide constructors when processing
> > > +   a noexcept-expression.  */
> > > +|| cp_noexcept_operand);
> > 
> > It seems weird that we're performing constant evaluation within an
> > unevaluated operand.  Would it make sense to also fix this a second way
> > by avoiding constant evaluation from maybe_constant_init when
> > cp_unevaluated_operand && !manifestly_const_eval, like in
> > maybe_constant_value?
> 
> Sounds good.

Hmm, while working on this I noticed we currently don't reject a version of
g++.dg/cpp2a/constexpr-inst1.C that list initializes an aggregate instead of
int (ever since r12-4425-g1595fe44e11a96):

  struct A { int m; };
  template constexpr int f() { return T::value; }
  template void h(decltype(A{B ? f() : 0})); // was 
int{...}
  template void h(...);
  void x() {
h(0); // OK?
  }

ISTM we should instantiate f here for the same reason we do in the
original version of the testcase, and for that to happen we need to
pass manifestly_const_eval=true in massage_init_elt.  Does that seem
reasonable?



Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-09 Thread Jason Merrill via Gcc-patches

On 3/9/23 14:32, Patrick Palka wrote:

On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:


When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
  gcc/cp/constexpr.cc | 6 +-
  gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
  2 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  
/* We used to shortcut trivial constructor/op= here, but nowadays

   we can only get a trivial function here with -fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);


It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in maybe_constant_value?


Sounds good.


IIUC since we could still have an evaluated subexpression withis
noexcept, the two fixes would be complementary.

  
bool non_constant_args = false;

new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902
--
2.39.2








Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-09 Thread Patrick Palka via Gcc-patches
On Mon, 6 Mar 2023, Marek Polacek via Gcc-patches wrote:

> When processing a noexcept, constructors aren't elided: build_over_call
> has
>/* It's unsafe to elide the constructor when handling
>   a noexcept-expression, it may evaluate to the wrong
>   value (c++/53025).  */
>&& (force_elide || cp_noexcept_operand == 0))
> so the assert I added recently needs to be relaxed a little bit.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
>   PR c++/109030
> 
> gcc/cp/ChangeLog:
> 
>   * constexpr.cc (cxx_eval_call_expression): Relax assert.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/cpp0x/noexcept77.C: New test.
> ---
>  gcc/cp/constexpr.cc | 6 +-
>  gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
>  2 files changed, 14 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 364695b762c..5384d0e8e46 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
> tree t,
>  
>/* We used to shortcut trivial constructor/op= here, but nowadays
>   we can only get a trivial function here with -fno-elide-constructors.  
> */
> -  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
> +  gcc_checking_assert (!trivial_fn_p (fun)
> +|| !flag_elide_constructors
> +/* We don't elide constructors when processing
> +   a noexcept-expression.  */
> +|| cp_noexcept_operand);

It seems weird that we're performing constant evaluation within an
unevaluated operand.  Would it make sense to also fix this a second way
by avoiding constant evaluation from maybe_constant_init when
cp_unevaluated_operand && !manifestly_const_eval, like in maybe_constant_value?
IIUC since we could still have an evaluated subexpression withis
noexcept, the two fixes would be complementary.

>  
>bool non_constant_args = false;
>new_call.bindings
> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
> b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> new file mode 100644
> index 000..16db8eb79ee
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
> @@ -0,0 +1,9 @@
> +// PR c++/109030
> +// { dg-do compile { target c++11 } }
> +
> +struct foo { };
> +
> +struct __as_receiver {
> +  foo empty_env;
> +};
> +void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }
> 
> base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902
> -- 
> 2.39.2
> 
> 



Re: [PATCH] c++: noexcept and copy elision [PR109030]

2023-03-07 Thread Jason Merrill via Gcc-patches

On 3/6/23 18:59, Marek Polacek wrote:

When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK.


PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
  gcc/cp/constexpr.cc | 6 +-
  gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
  2 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  
/* We used to shortcut trivial constructor/op= here, but nowadays

   we can only get a trivial function here with -fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);
  
bool non_constant_args = false;

new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902




[PATCH] c++: noexcept and copy elision [PR109030]

2023-03-06 Thread Marek Polacek via Gcc-patches
When processing a noexcept, constructors aren't elided: build_over_call
has
 /* It's unsafe to elide the constructor when handling
a noexcept-expression, it may evaluate to the wrong
value (c++/53025).  */
 && (force_elide || cp_noexcept_operand == 0))
so the assert I added recently needs to be relaxed a little bit.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/109030

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Relax assert.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/noexcept77.C: New test.
---
 gcc/cp/constexpr.cc | 6 +-
 gcc/testsuite/g++.dg/cpp0x/noexcept77.C | 9 +
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept77.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 364695b762c..5384d0e8e46 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2869,7 +2869,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
 
   /* We used to shortcut trivial constructor/op= here, but nowadays
  we can only get a trivial function here with -fno-elide-constructors.  */
-  gcc_checking_assert (!trivial_fn_p (fun) || !flag_elide_constructors);
+  gcc_checking_assert (!trivial_fn_p (fun)
+  || !flag_elide_constructors
+  /* We don't elide constructors when processing
+ a noexcept-expression.  */
+  || cp_noexcept_operand);
 
   bool non_constant_args = false;
   new_call.bindings
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept77.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
new file mode 100644
index 000..16db8eb79ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept77.C
@@ -0,0 +1,9 @@
+// PR c++/109030
+// { dg-do compile { target c++11 } }
+
+struct foo { };
+
+struct __as_receiver {
+  foo empty_env;
+};
+void sched(foo __fun) noexcept(noexcept(__as_receiver{__fun})) { }

base-commit: dfb14cdd796ad9df6b5f2def047ef36b29385902
-- 
2.39.2