[Bug lto/94822] New: ICE in lto with option -Warray-bounds and -fno-use-linker-plugin

lizekun1 at huawei dot com gcc-bugzilla@gcc.gnu.org
Tue Apr 28 13:58:38 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94822

            Bug ID: 94822
           Summary: ICE in lto with option -Warray-bounds and
                    -fno-use-linker-plugin
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: lto
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lizekun1 at huawei dot com
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

Created attachment 48393
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48393&action=edit
gcc10-lto-constructor-array-bounds.patch

Hi,
  I find an ICE when testing GCC10.0 on aarch64 at '-O3 -flto
-fno-use-linker-plugin -Warray-bounds' with POCs below:

test.h
---

typedef struct {
  int i;
  int ints[];
} struct_t;

---

test0.c
---

/* { dg-lto-do link } */

#include "test.h"

extern struct_t my_struct;

int main() {
return my_struct.ints[1];
}

---

test1.c
---

#include "test.h"

struct_t my_struct = {
20,
{ 1, 2 }
};

---

GCC version:
gcc version 10.0.1 20200421 (experimental)

Runcommand:
gcc -O3 -flto -fno-use-linker-plugin -Warray-bounds -c -o test0.o test0.c
gcc -O3 -flto -fno-use-linker-plugin -Warray-bounds -c -o test1.o test1.c
gcc test0.o test1.o -flto -Warray-bounds -fno-use-linker-plugin -o test.exe

Stack dump:
during GIMPLE pass: vrp
test0.c: In function 'main':
test0.c:7:5: internal compiler error: tree check: expected constructor, have
error_mark in get_initializer_for, at tree.c:13565
    7 | int main() {
      |     ^
0x15d8fc7 tree_check_failed(tree_node const*, char const*, int, char const*,
...)
        /home/lzk /gcc-10.0/gcc/tree.c:9685
0x9b0a37 tree_check(tree_node*, char const*, int, char const*, tree_code)
        /home/lzk /gcc-10.0/gcc/tree.h:3278
0x15eafdf get_initializer_for
        /home/lzk gcc-10.0/gcc/tree.c:13565
0x15eb73f component_ref_size(tree_node*, bool*)
        /home/lzk/ gcc-10.0/gcc/tree.c:13678
0x15a2037 vrp_prop::check_array_ref(unsigned int, tree_node*, bool)
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:3525
0x15a46c3 check_array_bounds
        /home/lzk /gcc-10.0/gcc/tree-vrp.c:4062
0x15e3cc3 walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*),
void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*,
tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*),
void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*))
        /home/lzk/gcc-10.0/gcc/tree.c:11954
0xd2cd37 walk_gimple_op(gimple*, tree_node* (*)(tree_node**, int*, void*),
walk_stmt_info*)
        /home/lzk/gcc-10.0/gcc/gimple-walk.c:202
0x15a485b check_array_bounds_dom_walker::before_dom_children(basic_block_def*)
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:4120
0x1f8c863 dom_walker::walk(basic_block_def*)
        /home/lzk/gcc-10.0/gcc/domwalk.c:309
0x15a48b7 vrp_prop::check_all_array_refs()
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:4137
0x15a805f vrp_prop::vrp_finalize(bool)
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:5209
0x15a80cb execute_vrp
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:5277
0x15a82fb execute
        /home/lzk/gcc-10.0/gcc/tree-vrp.c:5359

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.

My proposed fix is:
---
diff --git a/gcc/tree.c b/gcc/tree.c
index 63dc6730b2b..385c22e667f 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13719,6 +13719,13 @@ component_ref_size (tree ref, bool *inte
        the initializer of the BASE object if it has one.  */
     if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE)
       {
+       varpool_node *vnode;
+       if (TREE_CODE (init) == ERROR_MARK
+           && in_lto_p
+           && VAR_P (base)
+           && (vnode = varpool_node::get (base)
+               ? varpool_node::get (base)->ultimate_alias_target () : NULL))
+         init = vnode->get_constructor ();
        init = get_initializer_for (init, member);
        if (init)
          {

---
any suggestion?


More information about the Gcc-bugs mailing list