Bootstrapped/tested on x86_64-unknown-linux-gnu, pushed.

This ICE appears because gcc will stream it to the function_body section
when processing the variable with the initial value of the constructor
type, and the error_mark_node to the decls section.
When recompiling, the value obtained with DECL_INITIAL will be error_mark.

2020-04-29  Richard Biener  <rguent...@suse.de>
            Li Zekun  <lizek...@huawei.com>

        PR lto/94822
        * tree.c (component_ref_size): Guard against error_mark_node
        DECL_INITIAL as it happens with LTO.

        * gcc.dg/lto/pr94822_0.c: New testcase.
        * gcc.dg/lto/pr94822_1.c: Alternate file.
        * gcc.dg/lto/pr94822.h: Likewise.
---
 gcc/testsuite/gcc.dg/lto/pr94822.h   |  4 ++++
 gcc/testsuite/gcc.dg/lto/pr94822_0.c | 10 ++++++++
 gcc/testsuite/gcc.dg/lto/pr94822_1.c |  6 +++++
 gcc/tree.c                           | 35 ++++++++++++++--------------
 4 files changed, 38 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/lto/pr94822.h
 create mode 100644 gcc/testsuite/gcc.dg/lto/pr94822_0.c
 create mode 100644 gcc/testsuite/gcc.dg/lto/pr94822_1.c

diff --git a/gcc/testsuite/gcc.dg/lto/pr94822.h 
b/gcc/testsuite/gcc.dg/lto/pr94822.h
new file mode 100644
index 00000000000..d9e6c3da645
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr94822.h
@@ -0,0 +1,4 @@
+typedef struct {
+  int i;
+  int ints[];
+} struct_t;
diff --git a/gcc/testsuite/gcc.dg/lto/pr94822_0.c 
b/gcc/testsuite/gcc.dg/lto/pr94822_0.c
new file mode 100644
index 00000000000..698c0928a81
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr94822_0.c
@@ -0,0 +1,10 @@
+/* { dg-lto-do link } */
+
+#include "pr94822.h"
+
+extern struct_t my_struct;
+
+int main() {
+ return my_struct.ints[1];
+}
+
diff --git a/gcc/testsuite/gcc.dg/lto/pr94822_1.c 
b/gcc/testsuite/gcc.dg/lto/pr94822_1.c
new file mode 100644
index 00000000000..a7ace71680f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr94822_1.c
@@ -0,0 +1,6 @@
+#include "pr94822.h"
+
+struct_t my_struct = {
+ 20,
+ { 1, 2 }
+};
diff --git a/gcc/tree.c b/gcc/tree.c
index e28b29580ca..e451401822c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13723,24 +13723,25 @@ component_ref_size (tree ref, bool 
*interior_zero_length /* = NULL */)
     /* MEMBER is a true flexible array member.  Compute its size from
        the initializer of the BASE object if it has one.  */
     if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE)
-      {
-       init = get_initializer_for (init, member);
-       if (init)
-         {
-           memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
-           if (tree refsize = TYPE_SIZE_UNIT (reftype))
-             {
-               /* Use the larger of the initializer size and the tail
-                  padding in the enclosing struct.  */
-               poly_int64 rsz = tree_to_poly_int64 (refsize);
-               rsz -= baseoff;
-               if (known_lt (tree_to_poly_int64 (memsize), rsz))
-                 memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
-             }
+      if (init != error_mark_node)
+       {
+         init = get_initializer_for (init, member);
+         if (init)
+           {
+             memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
+             if (tree refsize = TYPE_SIZE_UNIT (reftype))
+               {
+                 /* Use the larger of the initializer size and the tail
+                    padding in the enclosing struct.  */
+                 poly_int64 rsz = tree_to_poly_int64 (refsize);
+                 rsz -= baseoff;
+                 if (known_lt (tree_to_poly_int64 (memsize), rsz))
+                   memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
+               }
 
-           baseoff = 0;
-         }
-      }
+             baseoff = 0;
+           }
+       }
 
   if (!memsize)
     {
-- 
2.25.1

Reply via email to