Message ID | ZoRbDh2OH27tDYhQ@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Fix ICE on constexpr placement new [PR115754] | expand |
On 7/2/24 3:54 PM, Jakub Jelinek wrote: > Hi! > > C++26 is making in P2747R2 paper placement new constexpr. > While working on a patch for that, I've noticed we ICE starting with > GCC 14 on the following testcase. > The problem is that e.g. for the void * to sometype * casts checks, > we really assume the casts have their operand constant evaluated > as prvalue, but on the testcase the cast itself is evaluated with > vc_discard and that means op can end up e.g. a VAR_DECL which the > later code doesn't like and asserts on. > If the result type is void, we don't really need the cast operand > for anything, so can use vc_discard for the recursive call, > VIEW_CONVERT_EXPR can appear on the lhs, so we need to honor the > lval but otherwise the patch uses vc_prvalue. > I'd like to get this patch in before the rest of P2747R2 implementation, > so that it can be backported to 14.2 later on. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK. > 2024-07-02 Jakub Jelinek <jakub@redhat.com> > Jason Merrill <jason@redhat.com> > > PR c++/115754 > * constexpr.cc (cxx_eval_constant_expression) <case CONVERT_EXPR>: > For conversions to void, pass vc_discard to the recursive call > and otherwise for tcode other than VIEW_CONVERT_EXPR pass vc_prvalue. > > * g++.dg/cpp26/pr115754.C: New test. > > --- gcc/cp/constexpr.cc.jj 2024-05-08 10:16:53.966824718 +0200 > +++ gcc/cp/constexpr.cc 2024-07-02 18:47:49.646843559 +0200 > @@ -8103,7 +8103,10 @@ cxx_eval_constant_expression (const cons > tree oldop = TREE_OPERAND (t, 0); > > tree op = cxx_eval_constant_expression (ctx, oldop, > - lval, > + VOID_TYPE_P (TREE_TYPE (t)) > + ? vc_discard > + : tcode == VIEW_CONVERT_EXPR > + ? lval : vc_prvalue, > non_constant_p, overflow_p); > if (*non_constant_p) > return t; > --- gcc/testsuite/g++.dg/cpp26/pr115754.C.jj 2024-07-02 18:40:08.107750189 +0200 > +++ gcc/testsuite/g++.dg/cpp26/pr115754.C 2024-07-02 18:39:57.110890921 +0200 > @@ -0,0 +1,36 @@ > +// PR c++/115754 > +// { dg-do compile { target c++26 } } > + > +namespace std > +{ > + using size_t = decltype (sizeof 0); > + > + template <typename T> > + struct allocator > + { > + constexpr allocator () noexcept {} > + > + constexpr T *allocate (size_t n) > + { return static_cast<T *> (::operator new (n * sizeof(T))); } > + > + constexpr void > + deallocate (T *p, size_t n) > + { ::operator delete (p); } > + }; > +} > + > +constexpr void * > +operator new (std::size_t, void *p) noexcept > +{ return p; } > + > +constexpr bool > +foo () > +{ > + std::allocator<int> a; > + auto b = a.allocate (1); > + ::new (b) int (); > + a.deallocate (b, 1); > + return true; > +} > + > +constexpr bool a = foo (); > > Jakub >
--- gcc/cp/constexpr.cc.jj 2024-05-08 10:16:53.966824718 +0200 +++ gcc/cp/constexpr.cc 2024-07-02 18:47:49.646843559 +0200 @@ -8103,7 +8103,10 @@ cxx_eval_constant_expression (const cons tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, - lval, + VOID_TYPE_P (TREE_TYPE (t)) + ? vc_discard + : tcode == VIEW_CONVERT_EXPR + ? lval : vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return t; --- gcc/testsuite/g++.dg/cpp26/pr115754.C.jj 2024-07-02 18:40:08.107750189 +0200 +++ gcc/testsuite/g++.dg/cpp26/pr115754.C 2024-07-02 18:39:57.110890921 +0200 @@ -0,0 +1,36 @@ +// PR c++/115754 +// { dg-do compile { target c++26 } } + +namespace std +{ + using size_t = decltype (sizeof 0); + + template <typename T> + struct allocator + { + constexpr allocator () noexcept {} + + constexpr T *allocate (size_t n) + { return static_cast<T *> (::operator new (n * sizeof(T))); } + + constexpr void + deallocate (T *p, size_t n) + { ::operator delete (p); } + }; +} + +constexpr void * +operator new (std::size_t, void *p) noexcept +{ return p; } + +constexpr bool +foo () +{ + std::allocator<int> a; + auto b = a.allocate (1); + ::new (b) int (); + a.deallocate (b, 1); + return true; +} + +constexpr bool a = foo ();