static inline __attribute__((always_inline)) void bar (void) { addr:; static const unsigned long b __attribute__((__used__)) __attribute__((section("btable"))) = (unsigned long) &&addr; asm ("" : : "m" (b)); } void foo (void) { bar (); } generates at -O and higher a reference to undefined local label (and has one unused different label). If the body of bar is instead copied into foo () and the call removed, it works fine. I think this is related to the http://gcc.gnu.org/ml/gcc-patches/2005-06/msg01850.html changes, not sure why isn't the local var remapped in: /* Add local vars in this inlined callee to caller. */ t_step = id->src_cfun->unexpanded_var_list; for (; t_step; t_step = TREE_CHAIN (t_step)) { var = TREE_VALUE (t_step); if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var)) cfun->unexpanded_var_list = tree_cons (NULL_TREE, var, cfun->unexpanded_var_list); else cfun->unexpanded_var_list = tree_cons (NULL_TREE, remap_decl (var, id), cfun->unexpanded_var_list); } asm isn't written, but the variable IMHO still needs remapping, at least to get the LABEL_DECL in the initializer remapped. In C there shouldn't be a problem with ODR, in C++ not sure what happens if initializer of some inline fn local var has &&label in its initializer - issue an error?
Confirmed. "generates at -O and higher a reference to undefined local label" No it generates an undefined local label at all levels of optimization in 4.0.x and above (there was a bug about not supporting used on local static at -O0 which you are running into also).
Actually, even C generates one static var for all the inlined functions (in C within one object), so I'd say we just should mark functions containing local static variables with &&label in their initializers as non-inlinable, because anything else means we can't use the same variable for more than one inlined copy of the function. In that light the original testcase would just issue an error, as always_inline function can't be inlined, but e.g. void baz (unsigned long *); static inline void bar (void) { addr:; static unsigned long b = (unsigned long) &&addr; baz (&b); } void f1 (void) { bar (); } void f2 (void) { bar (); } would be a valid testcase that we don't handle properly.
won't fix in GCC-4.0.x. Adjusting milestone.
Open regression with no activity since February 14. Ping?
Subject: Bug 29484 Author: jakub Date: Thu Jan 3 08:33:57 2008 New Revision: 131300 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131300 Log: PR tree-optimization/29484 * tree-inline.c (inline_forbidden_p_2): New function. (inline_forbidden_p): Disallow inlining if some static var has an address of a local LABEL_DECL in its initializer. * doc/extend.texi (Labels as Values): Document &&foo behaviour vs. inlining. * gcc.c-torture/execute/20071220-1.c: New test. * gcc.c-torture/execute/20071220-2.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/execute/20071220-1.c trunk/gcc/testsuite/gcc.c-torture/execute/20071220-2.c Modified: trunk/gcc/ChangeLog trunk/gcc/doc/extend.texi trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-inline.c
Closing 4.1 branch.
Closing 4.2 branch, fixed in 4.3.