c++: Fix ICE with constexpr init and [[no_unique_address]] [PR93803]
authorMarek Polacek <polacek@redhat.com>
Mon, 24 Feb 2020 14:19:01 +0000 (09:19 -0500)
committerMarek Polacek <polacek@redhat.com>
Wed, 26 Feb 2020 15:01:51 +0000 (10:01 -0500)
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.

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/constexpr-init17.C [new file with mode: 0644]

index 0cc971dc625145bafb0c7ecb917d1cd9903a0d24..14894533f9b7e12b1541eb6f7147ce9d0b326188 100644 (file)
@@ -1,3 +1,9 @@
+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
index 128f760778bb84d5eba15c774a63aca6ae13dac0..3da1609cdaa968522e471e9f8bb37675f2070e41 100644 (file)
@@ -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)))
index aa5d41e5559307a8c348b7d081a10414f1f8111f..4f46c385403161266fa7178ad60b7d831b6f4e32 100644 (file)
@@ -1,3 +1,9 @@
+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
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-init16.C
new file mode 100644 (file)
index 0000000..16db297
--- /dev/null
@@ -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 (file)
index 0000000..34d9fe5
--- /dev/null
@@ -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{};