mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 12:00:11 -05:00
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>
46 lines
1.3 KiB
C
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{}; }
|