diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b9700ef27b..228aea7c546 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-01-25 Richard Guenther + + PR tree-optimization/47426 + * tree-ssa-structalias.c (ipa_pta_execute): Make externally + visible functions results escape. + 2011-01-25 Jakub Jelinek PR target/45701 diff --git a/gcc/testsuite/gcc.dg/torture/pr47426-1.c b/gcc/testsuite/gcc.dg/torture/pr47426-1.c new file mode 100644 index 00000000000..47dcff91302 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr47426-1.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-fipa-pta" } */ +/* { dg-additional-sources "pr47426-2.c" } */ + +void bar (int *i); + +static void +foo (int *i) +{ + if (*i) + bar (i); + if (*i) + __builtin_abort(); +} + +typedef void tfoo (int *); + +tfoo * +getfoo (void) +{ + return &foo; +} + diff --git a/gcc/testsuite/gcc.dg/torture/pr47426-2.c b/gcc/testsuite/gcc.dg/torture/pr47426-2.c new file mode 100644 index 00000000000..a22e902bce4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr47426-2.c @@ -0,0 +1,19 @@ +typedef void tfoo (int *); +tfoo *getfoo (void); + +void +bar (int *i) +{ + (*i)--; +} + +int +main () +{ + int i = 1; + getfoo ()(&i); + if (i) + __builtin_abort (); + return 0; +} + diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index a49f14bba13..cf1e817f377 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4435,12 +4435,14 @@ find_func_aliases (gimple origt) do_structure_copy (lhsop, rhsop); else { + enum tree_code code = gimple_assign_rhs_code (t); + get_constraint_for (lhsop, &lhsc); - if (gimple_assign_rhs_code (t) == POINTER_PLUS_EXPR) + if (code == POINTER_PLUS_EXPR) get_constraint_for_ptr_offset (gimple_assign_rhs1 (t), gimple_assign_rhs2 (t), &rhsc); - else if (gimple_assign_rhs_code (t) == BIT_AND_EXPR + else if (code == BIT_AND_EXPR && TREE_CODE (gimple_assign_rhs2 (t)) == INTEGER_CST) { /* Aligning a pointer via a BIT_AND_EXPR is offsetting @@ -4448,11 +4450,15 @@ find_func_aliases (gimple origt) get_constraint_for_ptr_offset (gimple_assign_rhs1 (t), NULL_TREE, &rhsc); } - else if ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t)) + else if ((CONVERT_EXPR_CODE_P (code) && !(POINTER_TYPE_P (gimple_expr_type (t)) && !POINTER_TYPE_P (TREE_TYPE (rhsop)))) || gimple_assign_single_p (t)) get_constraint_for_rhs (rhsop, &rhsc); + else if (truth_value_p (code)) + /* Truth value results are not pointer (parts). Or at least + very very unreasonable obfuscation of a part. */ + ; else { /* All other operations are merges. */ @@ -6827,11 +6833,34 @@ ipa_pta_execute (void) push_cfun (func); current_function_decl = node->decl; - /* For externally visible functions use local constraints for - their arguments. For local functions we see all callers - and thus do not need initial constraints for parameters. */ if (node->local.externally_visible) - intra_create_variable_infos (); + { + /* For externally visible functions use local constraints for + their arguments. For local functions we see all callers + and thus do not need initial constraints for parameters. */ + intra_create_variable_infos (); + + /* We also need to make function return values escape. Nothing + escapes by returning from main though. */ + if (!MAIN_NAME_P (DECL_NAME (node->decl))) + { + varinfo_t fi, rvi; + fi = lookup_vi_for_tree (node->decl); + rvi = first_vi_for_offset (fi, fi_result); + if (rvi && rvi->offset == fi_result) + { + struct constraint_expr includes; + struct constraint_expr var; + includes.var = escaped_id; + includes.offset = 0; + includes.type = SCALAR; + var.var = rvi->id; + var.offset = 0; + var.type = SCALAR; + process_constraint (new_constraint (includes, var)); + } + } + } /* Build constriants for the function body. */ FOR_EACH_BB_FN (bb, func)