* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131300
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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
+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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
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)
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;