diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-03 08:33:57 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-03 08:33:57 +0000 |
commit | 361c9aad59cd53541245e876f3b78953e87cff57 (patch) | |
tree | c01a04f37d6590c350dcd0b897f1ffa43b5099c8 /gcc/tree-inline.c | |
parent | bfe20447cb8ed0643e71f42a4277b643ed1f952f (diff) | |
download | gcc-361c9aad59cd53541245e876f3b78953e87cff57.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131300 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 1efc0edc2ed..ebb413ae9bc 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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; |