diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-01-03 09:33:57 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-01-03 09:33:57 +0100 |
commit | 2092ee7d08be8897d85309fbffc395602e67a3fd (patch) | |
tree | c01a04f37d6590c350dcd0b897f1ffa43b5099c8 /gcc/tree-inline.c | |
parent | 097392de6b7eb5cba34ed8f367ab79837d7cedd2 (diff) | |
download | gcc-2092ee7d08be8897d85309fbffc395602e67a3fd.zip gcc-2092ee7d08be8897d85309fbffc395602e67a3fd.tar.gz gcc-2092ee7d08be8897d85309fbffc395602e67a3fd.tar.bz2 |
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
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 1efc0ed..ebb413a 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; |