From: Marek Polacek Date: Mon, 24 Feb 2020 14:19:01 +0000 (-0500) Subject: c++: Fix ICE with constexpr init and [[no_unique_address]] [PR93803] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d6ff22074126d38829f25981de9d6940cd2a234c;p=gcc.git c++: Fix ICE with constexpr init and [[no_unique_address]] [PR93803] Here we crash when constexpr-initializing a class member of empty class type with [[no_unique_address]]. Without the attribute we would have a ctor (that initializes bar) of the form { .D.2173 = { .x = {} } } but with the attribute reduced_constant_expression_p gets { .x = {} } That means that "idx != field" is true for the latter and we see that foo, the base class of bar, is an empty class, so we want to look at the next initializable field (since empty class fields may not have an initializer). But in this case there are no more, therefore accessing DECL_CHAIN (field) crashes. Long story short, we need to avoid a crash on a null field when we're initializing a class that only contains an empty base class. While poking into this I discovered c++/93898, but that's a different problem. 2020-02-26 Marek Polacek PR c++/93803 - ICE with constexpr init and [[no_unique_address]]. * constexpr.c (reduced_constant_expression_p): Don't crash on a null field. * g++.dg/cpp2a/constexpr-init16.C: New test. * g++.dg/cpp2a/constexpr-init17.C: New test. --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0cc971dc625..14894533f9b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-02-26 Marek Polacek + + PR c++/93803 - ICE with constexpr init and [[no_unique_address]]. + * constexpr.c (reduced_constant_expression_p): Don't crash on a null + field. + 2020-02-24 Martin Sebor PR c++/93804 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 128f760778b..3da1609cdaa 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2603,16 +2603,14 @@ reduced_constant_expression_p (tree t) element. */ if (!reduced_constant_expression_p (val)) return false; + /* Empty class field may or may not have an initializer. */ + for (; field && idx != field; + field = next_initializable_field (DECL_CHAIN (field))) + if (!is_really_empty_class (TREE_TYPE (field), + /*ignore_vptr*/false)) + return false; if (field) - { - /* Empty class field may or may not have an initializer. */ - for (; idx != field; - field = next_initializable_field (DECL_CHAIN (field))) - if (!is_really_empty_class (TREE_TYPE (field), - /*ignore_vptr*/false)) - return false; - field = next_initializable_field (DECL_CHAIN (field)); - } + field = next_initializable_field (DECL_CHAIN (field)); } /* There could be a non-empty field at the end. */ for (; field; field = next_initializable_field (DECL_CHAIN (field))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aa5d41e5559..4f46c385403 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-02-26 Marek Polacek + + PR c++/93803 - ICE with constexpr init and [[no_unique_address]]. + * g++.dg/cpp2a/constexpr-init16.C: New test. + * g++.dg/cpp2a/constexpr-init17.C: New test. + 2020-02-26 Richard Sandiford PR middle-end/93843 diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C new file mode 100644 index 00000000000..16db2974f2a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C @@ -0,0 +1,15 @@ +// PR c++/93803 - ICE with constexpr init and [[no_unique_address]]. +// { dg-do compile { target c++2a } } + +struct empty { }; + +struct foo { + [[no_unique_address]] empty x; + constexpr foo() : x{} { } +}; + +struct bar : foo { + using foo::foo; +}; + +constexpr bar a{}; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init17.C new file mode 100644 index 00000000000..34d9fe58ecb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-init17.C @@ -0,0 +1,15 @@ +// PR c++/93803 - ICE with constexpr init and [[no_unique_address]]. +// { dg-do compile { target c++2a } } + +struct empty { }; + +struct foo { + [[no_unique_address]] empty x, x2, x3; + constexpr foo() : x{}, x2{} { } +}; + +struct bar : foo { + using foo::foo; +}; + +constexpr bar a{};