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?