Hi, this patch fixes ARM LTO failures caused by my ctor offlining patch. The problem is that error_mark_node used to mark offlined ctors is also used specially thorough varasm.c mostly as an altenrative to "no constructor". I am not quite sure this code is needed anyway as we don't output variables in programs with error, but bellow is safe fix that disables this path for LTO.
It also makes get_variable_section to stream in the constructor so local flags are computed correctly. Bootstrapped/regtested x86_64-linux and tested to fix ARM failures. Comitted. Honza PR lto/61802 * varasm.c (bss_initializer_p): Handle offlined ctors. (align_variable, get_variable_align): Likewise. (make_decl_one_only): Likewise. (default_binds_local_p_1): Likewise. (decl_binds_to_current_def_p): Likewise. (get_variable_section): Get constructor if it is offlined. (assemble_variable_contents): Sanity check that the caller streamed in the ctor in LTO. Index: varasm.c =================================================================== --- varasm.c (revision 212984) +++ varasm.c (working copy) @@ -956,7 +956,10 @@ bool bss_initializer_p (const_tree decl) { return (DECL_INITIAL (decl) == NULL - || DECL_INITIAL (decl) == error_mark_node + /* In LTO we have no errors in program; error_mark_node is used + to mark offlined constructors. */ + || (DECL_INITIAL (decl) == error_mark_node + && !in_lto_p) || (flag_zero_initialized_in_bss /* Leave constant zeroes in .rodata so they can be shared. */ @@ -1017,7 +1020,9 @@ align_variable (tree decl, bool dont_out #endif #ifdef CONSTANT_ALIGNMENT if (DECL_INITIAL (decl) != 0 - && DECL_INITIAL (decl) != error_mark_node) + /* In LTO we have no errors in program; error_mark_node is used + to mark offlined constructors. */ + && (in_lto_p || DECL_INITIAL (decl) != error_mark_node)) { unsigned int const_align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align); @@ -1068,7 +1073,10 @@ get_variable_align (tree decl) align = data_align; #endif #ifdef CONSTANT_ALIGNMENT - if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node) + if (DECL_INITIAL (decl) != 0 + /* In LTO we have no errors in program; error_mark_node is used + to mark offlined constructors. */ + && (in_lto_p || DECL_INITIAL (decl) != error_mark_node)) { unsigned int const_align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align); @@ -1092,13 +1100,20 @@ get_variable_section (tree decl, bool pr { addr_space_t as = ADDR_SPACE_GENERIC; int reloc; - symtab_node *snode = symtab_node::get (decl); - if (snode) - decl = snode->ultimate_alias_target ()->decl; + varpool_node *vnode = varpool_node::get (decl); + if (vnode) + { + vnode = vnode->ultimate_alias_target (); + decl = vnode->decl; + } if (TREE_TYPE (decl) != error_mark_node) as = TYPE_ADDR_SPACE (TREE_TYPE (decl)); + /* We need the constructor to figure out reloc flag. */ + if (vnode) + vnode->get_constructor (); + if (DECL_COMMON (decl)) { /* If the decl has been given an explicit section name, or it resides @@ -1963,6 +1978,9 @@ assemble_variable_contents (tree decl, c if (!dont_output_data) { + /* Caller is supposed to use varpool_get_constructor when it wants + to output the body. */ + gcc_assert (!in_lto_p || DECL_INITIAL (decl) != error_mark_node); if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node && !initializer_zerop (DECL_INITIAL (decl))) @@ -5890,7 +5908,8 @@ make_decl_one_only (tree decl, tree comd symbol->set_comdat_group (comdat_group); } else if (TREE_CODE (decl) == VAR_DECL - && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) + && (DECL_INITIAL (decl) == 0 + || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node))) DECL_COMMON (decl) = 1; else { @@ -6752,7 +6771,7 @@ default_binds_local_p_1 (const_tree exp, else if (DECL_COMMON (exp) && !resolved_locally && (DECL_INITIAL (exp) == NULL - || DECL_INITIAL (exp) == error_mark_node)) + || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node))) local_p = false; /* Otherwise we're left with initialized (or non-common) global data which is of necessity defined locally. */ @@ -6807,7 +6826,7 @@ decl_binds_to_current_def_p (const_tree return false; if (DECL_COMMON (decl) && (DECL_INITIAL (decl) == NULL - || DECL_INITIAL (decl) == error_mark_node)) + || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node))) return false; if (DECL_EXTERNAL (decl)) return false;