diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d5d07197e85..bccdea9ec24 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2008-09-09 Richard Guenther + + PR middle-end/37354 + PR middle-end/30165 + * gimplify.c (gimplify_conversion): Change conversions of + non-register type to VIEW_CONVERT_EXPRs. + (gimplify_addr_expr): If we need to make the operand + addressable make sure to use a properly initialized + temporary for that so it gets a valid gimple store. + 2008-09-09 Aldy Hernandez * function.h (struct function): Add function_start_locus. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c1f5744d7a8..55c5fb25889 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1872,6 +1872,12 @@ gimplify_conversion (tree *expr_p) canonicalize_addr_expr (expr_p); } + /* If we have a conversion to a non-register type force the + use of a VIEW_CONVERT_EXPR instead. */ + if (!is_gimple_reg_type (TREE_TYPE (*expr_p))) + *expr_p = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p), + TREE_OPERAND (*expr_p, 0)); + return GS_OK; } @@ -4555,20 +4561,31 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* Mark the RHS addressable. */ ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p, is_gimple_addressable, fb_either); - if (ret != GS_ERROR) - { - op0 = TREE_OPERAND (expr, 0); + if (ret == GS_ERROR) + break; - /* For various reasons, the gimplification of the expression - may have made a new INDIRECT_REF. */ - if (TREE_CODE (op0) == INDIRECT_REF) - goto do_indirect_ref; + /* We cannot rely on making the RHS addressable if it is + a temporary created by gimplification. In this case create a + new temporary that is initialized by a copy (which will + become a store after we mark it addressable). + This mostly happens if the frontend passed us something that + it could not mark addressable yet, like a fortran + pass-by-reference parameter (int) floatvar. */ + if (is_gimple_formal_tmp_var (TREE_OPERAND (expr, 0))) + TREE_OPERAND (expr, 0) + = get_initialized_tmp_var (TREE_OPERAND (expr, 0), pre_p, post_p); - /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */ - recompute_tree_invariant_for_addr_expr (expr); + op0 = TREE_OPERAND (expr, 0); - mark_addressable (TREE_OPERAND (expr, 0)); - } + /* For various reasons, the gimplification of the expression + may have made a new INDIRECT_REF. */ + if (TREE_CODE (op0) == INDIRECT_REF) + goto do_indirect_ref; + + /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */ + recompute_tree_invariant_for_addr_expr (expr); + + mark_addressable (TREE_OPERAND (expr, 0)); break; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2d1822705e5..5393493a65b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-09-09 Richard Guenther + + PR middle-end/37354 + PR middle-end/30165 + * g++.dg/torture/pr37354.C: New testcase. + 2008-09-09 Aldy Hernandez * gcc.dg/always_inline.c: Place error message on function diff --git a/gcc/testsuite/g++.dg/torture/pr37354.C b/gcc/testsuite/g++.dg/torture/pr37354.C new file mode 100644 index 00000000000..acdf2911063 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr37354.C @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +class GenericClass; +struct AlsaDriver +{ + virtual int _read (unsigned nframes); +}; +typedef void (GenericClass::*GenericMemFuncType) (); +GenericMemFuncType m_pFunction; +void AlsaDriver1 () +{ + m_pFunction = reinterpret_cast < GenericMemFuncType > (&AlsaDriver::_read); +} +