160 lines
3.5 KiB
Diff
160 lines
3.5 KiB
Diff
|
2007-12-20 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.
|
||
|
|
||
|
* gcc.c-torture/execute/20071220-1.c: New test.
|
||
|
* gcc.c-torture/execute/20071220-2.c: New test.
|
||
|
|
||
|
--- gcc/tree-inline.c.jj 2007-12-04 16:39:22.000000000 +0100
|
||
|
+++ gcc/tree-inline.c 2007-12-20 13:46:18.000000000 +0100
|
||
|
@@ -1951,6 +1951,27 @@ inline_forbidden_p_1 (tree *nodep, int *
|
||
|
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;
|
||
|
--- gcc/testsuite/gcc.c-torture/execute/20071220-1.c.jj 2007-12-20 14:29:04.000000000 +0100
|
||
|
+++ gcc/testsuite/gcc.c-torture/execute/20071220-1.c 2007-12-20 14:28:12.000000000 +0100
|
||
|
@@ -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;
|
||
|
+}
|
||
|
--- gcc/testsuite/gcc.c-torture/execute/20071220-2.c.jj 2007-12-20 14:29:13.000000000 +0100
|
||
|
+++ gcc/testsuite/gcc.c-torture/execute/20071220-2.c 2007-12-20 14:28:30.000000000 +0100
|
||
|
@@ -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;
|
||
|
+}
|