http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53476
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> 2012-12-13 13:49:47 UTC --- Reduced testcase: static int Wv10a __attribute__((weakref ("Wv10b"))); static int Wv10b __attribute__((weakref ("wv10"))); extern int wv10; extern void abort (void); int main () { if (!!&Wv10a) abort (); return 0; } fails to link at -O1 works with -O0. >From .000i.cgraph: Reclaiming functions: Reclaiming variables: Clearing address taken flags: Trivially needed variables: Removing variables: Wv10a Final Symbol table: ... Breakpoint 5, varpool_remove_unreferenced_decls () at /space/rguenther/src/svn/trunk/gcc/varpool.c:405 405 varpool_remove_node (node); (gdb) call debug_symtab_node((symtab_node)node) Wv10a/0 (Wv10a) @0x7ffff68fa068 Type: variable Visibility: external weak References: Wv10b/1 (alias) Referring: main/2 (addr) Availability: available Varpool flags: analyzed finalized so it's still refered to. if (cgraph_dump_file) fprintf (cgraph_dump_file, "Trivially needed variables:"); FOR_EACH_DEFINED_VARIABLE (node) { if (node->analyzed && (!varpool_can_remove_if_no_refs (node) /* We just expanded all function bodies. See if any of them needed the variable. */ || (!DECL_EXTERNAL (node->symbol.decl) && DECL_RTL_SET_P (node->symbol.decl)))) doesn't catch it because (gdb) call debug_tree (node->symbol.decl) <var_decl 0x7ffff68045f0 Wv10a type <integer_type 0x7ffff67f75e8 int public SI size <integer_cst 0x7ffff67fa0c0 constant 32> unit size <integer_cst 0x7ffff67fa0e0 constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff67f75e8 precision 32 min <integer_cst 0x7ffff67fa060 -2147483648> max <integer_cst 0x7ffff67fa080 2147483647> pointer_to_this <pointer_type 0x7ffff67ff2a0>> addressable used static external weak SI file t.c line 1 col 12 size <integer_cst 0x7ffff67fa0c0 32> unit size <integer_cst 0x7ffff67fa0e0 4> align 32 context <translation_unit_decl 0x7ffff6918000 D.1721> attributes <tree_list 0x7ffff68f3c08> (mem:SI (symbol_ref/i:DI ("Wv10a") <var_decl 0x7ffff68045f0 Wv10a>) [0 Wv10a+0 S4 A32]) chain <var_decl 0x7ffff6804688 Wv10b>> it has DECL_EXTERNAL set (but it also is TREE_STATIC and has RTL!). On the 4.7 branch we simply checked whether the DECL had RTL but didn't bother to check whether it does not have DECL_EXTERNAL set. I'd say either revert to 4.7 behavior here or do Index: varpool.c =================================================================== --- varpool.c (revision 194472) +++ varpool.c (working copy) @@ -358,7 +358,8 @@ varpool_remove_unreferenced_decls (void) && (!varpool_can_remove_if_no_refs (node) /* We just expanded all function bodies. See if any of them needed the variable. */ - || (!DECL_EXTERNAL (node->symbol.decl) + || (!(DECL_EXTERNAL (node->symbol.decl) + && !TREE_STATIC (node->symbol.decl)) && DECL_RTL_SET_P (node->symbol.decl)))) { enqueue_node (node, &first); testing reversal to 4.7 behavior.