Message ID | 20220509224107.483598-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: ICE with constexpr dtor on ARM [PR105529] | expand |
On 5/9/22 18:41, Marek Polacek wrote: > When compiling this test on ARM with -O, we ICE in cxx_eval_store_expression > while evaluating a CALL_EXPR allocator::~allocator (&D.4529). Its body > has this store: > > <retval> = this > > The RHS is evaluated into &D.4529 of type allocator *. The object, > <retval>, is of type void *. Their types don't match That seems like the bug, which I have a patch for. > so we go into the new > > if (empty_base || !(same_type_ignoring_top_level_qualifiers_p > (TREE_TYPE (init), type))) > { > empty_base = true; > gcc_assert (is_empty_class (TREE_TYPE (init))); > > branch where we crash because is_empty_class will always say false for > a pointer type. It seems like the new branch expects code like > > D.2181 = {} > > where the type of the LHS is the derived type and the type of the RHS is > the base type. But it only expects to see actual class types, not > pointers to them. With this patch we will do what we did before the > empty bases cleanup patch: set *valp and return the initializer. It seems reasonable to expect that the initializer has the same type as the target; otherwise other things are likely to get confused. I'll incorporate your testcases in my patch, thanks. > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > PR c++/105529 > > gcc/cp/ChangeLog: > > * constexpr.cc (cxx_eval_store_expression): Check CLASS_TYPE_P before > checking initialization of an empty base. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp2a/constexpr-dtor13.C: New test. > * g++.dg/cpp2a/constexpr-dtor14.C: New test. > --- > gcc/cp/constexpr.cc | 5 +++-- > gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C | 11 +++++++++++ > gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C | 13 +++++++++++++ > 3 files changed, 27 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > index e560d842e8c..e4498c15f1e 100644 > --- a/gcc/cp/constexpr.cc > +++ b/gcc/cp/constexpr.cc > @@ -5916,8 +5916,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, > > gcc_checking_assert (!*valp || (same_type_ignoring_top_level_qualifiers_p > (TREE_TYPE (*valp), type))); > - if (empty_base || !(same_type_ignoring_top_level_qualifiers_p > - (TREE_TYPE (init), type))) > + if (empty_base || (CLASS_TYPE_P (TREE_TYPE (init)) > + && !(same_type_ignoring_top_level_qualifiers_p > + (TREE_TYPE (init), type)))) > { > /* For initialization of an empty base, the original target will be > *(base*)this, evaluation of which resolves to the object > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C > new file mode 100644 > index 00000000000..7b289614fc1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C > @@ -0,0 +1,11 @@ > +// PR c++/105529 > +// { dg-do compile { target c++20 } } > +// { dg-options "-O" } > + > +struct allocator { > + constexpr ~allocator() {} > +}; > +struct S { > + S(int, int, allocator = allocator()); > +}; > +void to_string() { S(0, '\0'); } > diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C > new file mode 100644 > index 00000000000..9c55121eb8a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C > @@ -0,0 +1,13 @@ > +// PR c++/105529 > +// { dg-do compile { target c++20 } } > +// { dg-options "-O" } > +// Like constexpr-dtor13.C, except that allocator is not an empty class. > + > +struct allocator { > + constexpr ~allocator() {} > + int a; > +}; > +struct S { > + S(int, int, allocator = allocator()); > +}; > +void to_string() { S(0, '\0'); } > > base-commit: 8a39c7c128dbf4405821778724c5a1017ab12e06
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index e560d842e8c..e4498c15f1e 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -5916,8 +5916,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, gcc_checking_assert (!*valp || (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (*valp), type))); - if (empty_base || !(same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (init), type))) + if (empty_base || (CLASS_TYPE_P (TREE_TYPE (init)) + && !(same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (init), type)))) { /* For initialization of an empty base, the original target will be *(base*)this, evaluation of which resolves to the object diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C new file mode 100644 index 00000000000..7b289614fc1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor13.C @@ -0,0 +1,11 @@ +// PR c++/105529 +// { dg-do compile { target c++20 } } +// { dg-options "-O" } + +struct allocator { + constexpr ~allocator() {} +}; +struct S { + S(int, int, allocator = allocator()); +}; +void to_string() { S(0, '\0'); } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C new file mode 100644 index 00000000000..9c55121eb8a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor14.C @@ -0,0 +1,13 @@ +// PR c++/105529 +// { dg-do compile { target c++20 } } +// { dg-options "-O" } +// Like constexpr-dtor13.C, except that allocator is not an empty class. + +struct allocator { + constexpr ~allocator() {} + int a; +}; +struct S { + S(int, int, allocator = allocator()); +}; +void to_string() { S(0, '\0'); }