diff options
author | Marek Polacek <polacek@redhat.com> | 2024-12-10 18:43:56 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2024-12-19 11:07:18 -0500 |
commit | fa99002538bc91c869f3b1fd9af7f14e410e1e1a (patch) | |
tree | 2e5eb34b71657d9c1c517c3da2a39be90bd8e5f8 /gcc/testsuite/g++.dg/cpp0x | |
parent | fc95e8776cf4b11bbffc593167105883165b9e4c (diff) | |
download | gcc-fa99002538bc91c869f3b1fd9af7f14e410e1e1a.zip gcc-fa99002538bc91c869f3b1fd9af7f14e410e1e1a.tar.gz gcc-fa99002538bc91c869f3b1fd9af7f14e410e1e1a.tar.bz2 |
c++: ICE in TARGET_EXPR evaluation in cp_fold_r [PR117980]
This ICE started with the recent prvalue optimization (r15-6052). In
cp_fold_r we have:
if (tree &init = TARGET_EXPR_INITIAL (stmt))
{
cp_walk_tree (&init, cp_fold_r, data, NULL);
// ...
tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
What can happen here is that originally the TARGET_EXPR is:
TARGET_EXPR <D.2747, <<< Unknown tree: aggr_init_expr
5
__ct_comp
D.2747
(struct subrange *) <<< Unknown tree: void_cst >>>
&TARGET_EXPR <D.2707, {.it=TARGET_EXPR <D.2695, ...>}> >>>>
but after the first cp_walk_tree we fold the D.2707 TARGET_EXPR into:
TARGET_EXPR <D.2707, <<< Unknown tree: expr_stmt
D.2707.it = TARGET_EXPR <D.2695, ...> >>>>
and then we pass the EXPR_STMT to maybe_constant_init, with D.2707 as
the object. But their types don't match anymore, so we crash. We'd
have to pass D.2707.it as the object for it to work.
This patch adjusts cxx_eval_outermost_constant_expr to take the object's
type if available.
constexpr-prvalue3.C is reduced from a large std::ranges libstdc++ test.
PR c++/117980
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_outermost_constant_expr): If there's
an object to initialize, take its type. Don't set the type
in the constexpr dtor case.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-prvalue2.C: New test.
* g++.dg/cpp0x/constexpr-prvalue3.C: New test.
Co-authored-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp0x')
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C | 26 |
2 files changed, 41 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C new file mode 100644 index 0000000..4605323 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue2.C @@ -0,0 +1,15 @@ +// PR c++/117980 +// { dg-do compile { target c++11 } } +// { dg-options "-O" } + +struct S { + constexpr S(S &); // { dg-warning "used but never defined" } + ~S(); +}; +struct B { + S s; +}; +struct A { + B b; +}; +void fn(B b) { A{b}; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C new file mode 100644 index 0000000..a2eb12c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue3.C @@ -0,0 +1,26 @@ +// PR c++/117980 +// { dg-do compile { target c++11 } } +// { dg-options "-O" } + +struct _Safe_iterator { + _Safe_iterator(); + ~_Safe_iterator(); +}; +template <typename _Tp> +struct vector { + vector(int) {} + constexpr _Safe_iterator end() { + return _Safe_iterator(); + } +}; +template <typename It> struct sentinel { + It it; +}; +template <typename _Sent> +struct subrange { + subrange(sentinel<_Safe_iterator>) {} +}; +void test01() { + vector<int> v{0}; + subrange<sentinel<_Safe_iterator>>{sentinel<_Safe_iterator>{v.end()}}; +} |