re PR tree-optimization/29484 (tree-inline.c bug with local static vars)
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. From-SVN: r131300
This commit is contained in:
parent
097392de6b
commit
2092ee7d08
|
@ -1,3 +1,12 @@
|
|||
2008-01-03 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2007-12-19 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
PR tree-optimization/34635
|
||||
|
|
|
@ -370,6 +370,12 @@ This is more friendly to code living in shared libraries, as it reduces
|
|||
the number of dynamic relocations that are needed, and by consequence,
|
||||
allows the data to be read-only.
|
||||
|
||||
The @code{&&foo} expressions for the same label might have different values
|
||||
if the containing function is inlined or cloned. If a program relies on
|
||||
them being always the same, @code{__attribute__((__noinline__))} should
|
||||
be used to prevent inlining. If @code{&&foo} is used
|
||||
in a static variable initializer, inlining is forbidden.
|
||||
|
||||
@node Nested Functions
|
||||
@section Nested Functions
|
||||
@cindex nested functions
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2008-01-03 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/29484
|
||||
* gcc.c-torture/execute/20071220-1.c: New test.
|
||||
* gcc.c-torture/execute/20071220-2.c: New test.
|
||||
|
||||
2007-12-19 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
PR tree-optimization/34635
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* PR tree-optimization/29484 */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
void *__attribute__((noinline))
|
||||
baz (void **lab)
|
||||
{
|
||||
asm volatile ("" : "+r" (lab));
|
||||
return *lab;
|
||||
}
|
||||
|
||||
static inline
|
||||
int bar (void)
|
||||
{
|
||||
static void *b[] = { &&addr };
|
||||
void *p = baz (b);
|
||||
goto *p;
|
||||
addr:
|
||||
return 17;
|
||||
}
|
||||
|
||||
int __attribute__((noinline))
|
||||
f1 (void)
|
||||
{
|
||||
return bar ();
|
||||
}
|
||||
|
||||
int __attribute__((noinline))
|
||||
f2 (void)
|
||||
{
|
||||
return bar ();
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (f1 () != 17 || f1 () != 17 || f2 () != 17 || f2 () != 17)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* PR tree-optimization/29484 */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
void *__attribute__((noinline))
|
||||
baz (void **lab)
|
||||
{
|
||||
asm volatile ("" : "+r" (lab));
|
||||
return *lab;
|
||||
}
|
||||
|
||||
static inline
|
||||
int bar (void)
|
||||
{
|
||||
static void *b[] = { &&addr };
|
||||
baz (b);
|
||||
addr:
|
||||
return 17;
|
||||
}
|
||||
|
||||
int __attribute__((noinline))
|
||||
f1 (void)
|
||||
{
|
||||
return bar ();
|
||||
}
|
||||
|
||||
int __attribute__((noinline))
|
||||
f2 (void)
|
||||
{
|
||||
return bar ();
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (f1 () != 17 || f1 () != 17 || f2 () != 17 || f2 () != 17)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
|
@ -1951,6 +1951,27 @@ inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
static tree
|
||||
inline_forbidden_p_2 (tree *nodep, int *walk_subtrees,
|
||||
void *fnp)
|
||||
{
|
||||
tree node = *nodep;
|
||||
tree fn = (tree) fnp;
|
||||
|
||||
if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn)
|
||||
{
|
||||
inline_forbidden_reason
|
||||
= G_("function %q+F can never be inlined "
|
||||
"because it saves address of local label in a static variable");
|
||||
return node;
|
||||
}
|
||||
|
||||
if (TYPE_P (node))
|
||||
*walk_subtrees = 0;
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return subexpression representing possible alloca call, if any. */
|
||||
static tree
|
||||
inline_forbidden_p (tree fndecl)
|
||||
|
@ -1959,16 +1980,31 @@ inline_forbidden_p (tree fndecl)
|
|||
block_stmt_iterator bsi;
|
||||
basic_block bb;
|
||||
tree ret = NULL_TREE;
|
||||
struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
|
||||
tree step;
|
||||
|
||||
FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (fndecl))
|
||||
FOR_EACH_BB_FN (bb, fun)
|
||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
ret = walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
|
||||
inline_forbidden_p_1, fndecl);
|
||||
inline_forbidden_p_1, fndecl);
|
||||
if (ret)
|
||||
goto egress;
|
||||
}
|
||||
|
||||
for (step = fun->unexpanded_var_list; step; step = TREE_CHAIN (step))
|
||||
{
|
||||
tree decl = TREE_VALUE (step);
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& TREE_STATIC (decl)
|
||||
&& !DECL_EXTERNAL (decl)
|
||||
&& DECL_INITIAL (decl))
|
||||
ret = walk_tree_without_duplicates (&DECL_INITIAL (decl),
|
||||
inline_forbidden_p_2, fndecl);
|
||||
if (ret)
|
||||
goto egress;
|
||||
}
|
||||
|
||||
egress:
|
||||
input_location = saved_loc;
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue