Commit d6ff2207 by Marek Polacek

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  <polacek@redhat.com>

	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.
parent 759bd406
2020-02-26 Marek Polacek <polacek@redhat.com>
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 <msebor@redhat.com>
PR c++/93804
......
......@@ -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)))
......
2020-02-26 Marek Polacek <polacek@redhat.com>
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 <richard.sandiford@arm.com>
PR middle-end/93843
......
// 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{};
// 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{};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment