Files
gcc-reflection/gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue3.C
Marek Polacek f3f02493df c++: fix wrong-code with constexpr prvalue opt [PR118396]
The recent r15-6369 unfortunately caused a bad wrong-code issue.
Here we have

  TARGET_EXPR <D.2996, (void) (D.2996 = {.status=0, .data={._vptr.Foo=&_ZTV3Foo + 16}})>

and call cp_fold_r -> maybe_constant_init with object=D.2996.  In
cxx_eval_outermost_constant_expr we now take the type of the object
if present.  An object can't have type 'void' and so we continue to
evaluate the initializer.  That evaluates into a VOID_CST, meaning
we disregard the whole initializer, and terrible things ensue.

For non-simple TARGET_EXPRs, we should return ctx.ctor rather than
the result of cxx_eval_constant_expression.

	PR c++/118396
	PR c++/118523

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_eval_outermost_constant_expr): For non-simple
	TARGET_EXPRs, return ctx.ctor rather than the result of
	cxx_eval_constant_expression.  If TYPE and the type of R don't
	match, return the original expression.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/constexpr-prvalue4.C: New test.
	* g++.dg/cpp1y/constexpr-prvalue3.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
2025-01-21 09:57:46 -05:00

46 lines
1.3 KiB
C

// PR c++/118523
// { dg-do compile { target c++14 } }
// { dg-options "-O2 -Wall" }
struct __new_allocator {
constexpr __new_allocator() {}
__new_allocator(__new_allocator &) {}
};
template <typename> using __allocator_base = __new_allocator;
template <typename> struct allocator_traits;
template <typename> struct allocator : __allocator_base<int> {};
template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
using pointer = _Tp *;
template <typename _Up> using rebind_alloc = allocator<_Up>;
static void deallocate(allocator<_Tp>, pointer, long);
};
struct __alloc_traits : allocator_traits<allocator<int>> {};
struct _Vector_impl_data {
__alloc_traits::pointer _M_start;
__alloc_traits::pointer _M_end_of_storage;
constexpr _Vector_impl_data() : _M_start(), _M_end_of_storage() {}
};
struct _Vector_impl : __alloc_traits::rebind_alloc<int>, _Vector_impl_data {};
struct _Vector_base {
~_Vector_base() {
_M_deallocate(_M_impl._M_start,
_M_impl._M_end_of_storage - _M_impl._M_start);
}
_Vector_impl _M_impl;
void _M_deallocate(__alloc_traits::pointer __p, long __n) {
if (__p)
__alloc_traits::deallocate(_M_impl, __p, __n);
}
};
struct vector : protected _Vector_base {};
struct S {
vector a{};
};
struct B2 {
B2(S);
};
struct E : B2 {
E(S opts = {}) : B2{opts} {}
};
void fun() { E{}; }