c++: Fix ICE on constexpr placement new [PR115754]
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. 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.
This commit is contained in:
parent
beb7a418aa
commit
1250540a98
2 changed files with 40 additions and 1 deletions
|
@ -8103,7 +8103,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
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;
|
||||
|
|
36
gcc/testsuite/g++.dg/cpp26/pr115754.C
Normal file
36
gcc/testsuite/g++.dg/cpp26/pr115754.C
Normal file
|
@ -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 ();
|
Loading…
Add table
Reference in a new issue