On Thu, Feb 27, 2025 at 01:15:12PM -0500, Jason Merrill wrote:
> On 2/20/25 9:51 AM, Marek Polacek wrote:
> > Now with the test fixed.
> >
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > -- >8 --
> > In this PR we crash in cxx_eval_constant_expression/GOTO_EXPR on:
> >
> > gcc_assert (cxx_dialect >= cxx23);
> >
> > The code obviously doesn't expect to see a goto pre-C++23. But we can
> > get here with the new prvalue optimization. In this test we found
> > ourselves in synthesize_method for X::X(). This function calls:
> >
> > a) finish_function, which does cp_genericize -> ... -> genericize_c_loops,
> > which creates the GOTO_EXPR;
> > b) expand_or_defer_fn -> maybe_clone_body -> ... -> cp_fold_function
> > where we reach the new maybe_constant_init call and crash on the
> > goto.
>
> Hmm, this looks like bad recursion; finish_function wants to fold before
> genericize, but then beacuse maybe_clone_body calls finish_function, we end
> up folding again after genericize.
>
> Maybe we should call maybe_clone_body directly from finish_function rather
> than from expand_or_defer?
Probably best to leave that to 16; I wonder what kind of trouble that
would unravel.
> But the patch is OK as is.
Thanks.
> > Since we can validly get to that assert, I think we should just remove
> > it. I don't see other similar asserts like this one.
> >
> > PR c++/118928
> >
> > gcc/cp/ChangeLog:
> >
> > * constexpr.cc (cxx_eval_constant_expression) <case GOTO_EXPR>: Remove
> > an assert.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp0x/constexpr-prvalue5.C: New test.
> > ---
> > gcc/cp/constexpr.cc | 1 -
> > .../g++.dg/cpp0x/constexpr-prvalue5.C | 24 +++++++++++++++++++
> > 2 files changed, 24 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue5.C
> >
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 59dd0668af3..c68666cc5dd 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -8691,7 +8691,6 @@ cxx_eval_constant_expression (const constexpr_ctx
> > *ctx, tree t,
> > *jump_target = TREE_OPERAND (t, 0);
> > else
> > {
> > - gcc_assert (cxx_dialect >= cxx23);
> > if (!ctx->quiet)
> > error_at (loc, "%<goto%> is not a constant expression");
> > *non_constant_p = true;
> > diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue5.C
> > b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue5.C
> > new file mode 100644
> > index 00000000000..1f847bbe183
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue5.C
> > @@ -0,0 +1,24 @@
> > +// PR c++/118928
> > +// { dg-do compile { target c++11 } }
> > +// { dg-options "-O" }
> > +
> > +using size_t = decltype(sizeof(0));
> > +
> > +namespace std {
> > +template <typename T> struct initializer_list {
> > + const T *_M_array;
> > + size_t _M_len;
> > +};
> > +struct S {
> > + constexpr S(const char *); // { dg-warning "used but never defined" }
> > +};
> > +struct vector {
> > + constexpr vector(initializer_list<S>) {}
> > +};
> > +}
> > +struct Y {
> > + std::vector v;
> > +};
> > +struct X {
> > + Y y{{""}};
> > +} x;
> >
> > base-commit: a2755339c6c9832467c573d956e91565943ecdc1
>
Marek