[PATCH] Clean up the gimple type verifier [2/2]
Richard Guenther
rguenther@suse.de
Thu Sep 4 15:39:00 GMT 2008
On Thu, 4 Sep 2008, Richard Guenther wrote:
> On Wed, 3 Sep 2008, Richard Guenther wrote:
>
> >
> > This splits apart and "completes" verifying of GIMPLE_ASSIGN.
> > Unfortunately during the time the checks were incomplete/disabled
> > we have gathered some new problems (maybe due to tuplification of
> > the gimplifier, I'll have to investigate).
> >
> > Bootstrapped on x86_64-unknown-linux-gnu, the C testsuite is clean,
> > as are the Ada, java, objc and libstdc++ ones. C++ has got one
> > problem (back?):
The following patch is an update which addresses all frontend issues
in addition to doing the GIMPLE_ASSIGN verifier split-up.
Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?
Thanks,
Richard.
2008-09-03 Richard Guenther <rguenther@suse.de>
* tree-cfg.c (verify_types_in_gimple_assign): Rename to ...
(verify_gimple_assign): ... this. Split into ...
(verify_gimple_assign_unary): ... this,
(verify_gimple_assign_binary): ... that,
(verify_gimple_assign_single): ... and this.
(verify_types_in_gimple_stmt): Call verify_gimple_assign.
* tree.def (PREDICT_EXPR): Change to tcc_expression.
PR middle-end/37354
* 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.
* g++.dg/torture/pr37354.C: New testcase.
fortran/
* trans-array.c (gfc_conv_array_parameter): Use correct types
in building COND_EXPRs.
* trans-expr.c (gfc_conv_missing_dummy): Likewise.
* trans-intrinsics.c (gfc_conv_intrinsic_merge): Likewise.
* gfortran.dg/internal_pack_4.f90: Adjust pattern.
cp/
* rtti.c (build_dynamic_cast_1): Convert the COND_EXPR
result to the correct type.
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c 2008-09-04 13:50:37.000000000 +0200
--- trunk/gcc/tree-cfg.c 2008-09-04 13:50:38.000000000 +0200
*************** verify_gimple_comparison (tree type, tre
*** 3257,3293 ****
return false;
}
! /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
! is a problem, otherwise false.
!
! Verify that the types of the LHS and the RHS operands are
! compatible. This verification largely depends on what kind of
! operation is done on the RHS of the assignment. It is not always
! the case that all the types of the operands must match (e.g., 'a =
! (unsigned long) b' or 'ptr = ptr + 1'). */
static bool
! verify_types_in_gimple_assign (gimple stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs = gimple_assign_lhs (stmt);
- tree rhs1 = gimple_assign_rhs1 (stmt);
- tree rhs2 = (gimple_num_ops (stmt) == 3) ? gimple_assign_rhs2 (stmt) : NULL;
tree lhs_type = TREE_TYPE (lhs);
tree rhs1_type = TREE_TYPE (rhs1);
- tree rhs2_type = (rhs2) ? TREE_TYPE (rhs2) : NULL;
! /* Special codes we cannot handle via their class. */
switch (rhs_code)
{
CASE_CONVERT:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in conversion");
- return true;
- }
-
/* Allow conversions between integral types and pointers only if
there is no sign or zero extension involved. */
if (((POINTER_TYPE_P (lhs_type) && INTEGRAL_TYPE_P (rhs1_type))
--- 3257,3293 ----
return false;
}
! /* Verify a gimple assignment statement STMT with an unary rhs.
! Returns true if anything is wrong. */
static bool
! verify_gimple_assign_unary (gimple stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs = gimple_assign_lhs (stmt);
tree lhs_type = TREE_TYPE (lhs);
+ tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs1_type = TREE_TYPE (rhs1);
! if (!is_gimple_reg (lhs)
! && !(optimize == 0
! && TREE_CODE (lhs_type) == COMPLEX_TYPE))
! {
! error ("non-register as LHS of unary operation");
! return true;
! }
!
! if (!is_gimple_val (rhs1))
! {
! error ("invalid operand in unary operation");
! return true;
! }
!
! /* First handle conversions. */
switch (rhs_code)
{
CASE_CONVERT:
{
/* Allow conversions between integral types and pointers only if
there is no sign or zero extension involved. */
if (((POINTER_TYPE_P (lhs_type) && INTEGRAL_TYPE_P (rhs1_type))
*************** verify_types_in_gimple_assign (gimple st
*** 3320,3331 ****
case FIXED_CONVERT_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in conversion");
- return true;
- }
-
if (!valid_fixed_convert_types_p (lhs_type, rhs1_type)
&& !valid_fixed_convert_types_p (rhs1_type, lhs_type))
{
--- 3320,3325 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3340,3351 ****
case FLOAT_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in int to float conversion");
- return true;
- }
-
if (!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
{
error ("invalid types in conversion to floating point");
--- 3334,3339 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3359,3370 ****
case FIX_TRUNC_EXPR:
{
- if (!is_gimple_val (rhs1))
- {
- error ("invalid operand in float to int conversion");
- return true;
- }
-
if (!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
{
error ("invalid types in conversion to integer");
--- 3347,3352 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3376,3389 ****
return false;
}
! case COMPLEX_EXPR:
{
! if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
! {
! error ("invalid operands in complex expression");
! return true;
! }
if (!TREE_CODE (lhs_type) == COMPLEX_TYPE
|| !(TREE_CODE (rhs1_type) == INTEGER_TYPE
|| SCALAR_FLOAT_TYPE_P (rhs1_type))
--- 3358,3432 ----
return false;
}
! case TRUTH_NOT_EXPR:
{
! }
!
! case NEGATE_EXPR:
! case ABS_EXPR:
! case BIT_NOT_EXPR:
! case PAREN_EXPR:
! case NON_LVALUE_EXPR:
! case CONJ_EXPR:
! case REDUC_MAX_EXPR:
! case REDUC_MIN_EXPR:
! case REDUC_PLUS_EXPR:
! case VEC_UNPACK_HI_EXPR:
! case VEC_UNPACK_LO_EXPR:
! case VEC_UNPACK_FLOAT_HI_EXPR:
! case VEC_UNPACK_FLOAT_LO_EXPR:
! break;
!
! default:
! gcc_unreachable ();
! }
!
! /* For the remaining codes assert there is no conversion involved. */
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion in unary operation");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
!
! return false;
! }
!
! /* Verify a gimple assignment statement STMT with a binary rhs.
! Returns true if anything is wrong. */
!
! static bool
! verify_gimple_assign_binary (gimple stmt)
! {
! enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
! tree lhs = gimple_assign_lhs (stmt);
! tree lhs_type = TREE_TYPE (lhs);
! tree rhs1 = gimple_assign_rhs1 (stmt);
! tree rhs1_type = TREE_TYPE (rhs1);
! tree rhs2 = gimple_assign_rhs2 (stmt);
! tree rhs2_type = TREE_TYPE (rhs2);
!
! if (!is_gimple_reg (lhs)
! && !(optimize == 0
! && TREE_CODE (lhs_type) == COMPLEX_TYPE))
! {
! error ("non-register as LHS of binary operation");
! return true;
! }
!
! if (!is_gimple_val (rhs1)
! || !is_gimple_val (rhs2))
! {
! error ("invalid operands in binary operation");
! return true;
! }
+ /* First handle operations that involve different types. */
+ switch (rhs_code)
+ {
+ case COMPLEX_EXPR:
+ {
if (!TREE_CODE (lhs_type) == COMPLEX_TYPE
|| !(TREE_CODE (rhs1_type) == INTEGER_TYPE
|| SCALAR_FLOAT_TYPE_P (rhs1_type))
*************** verify_types_in_gimple_assign (gimple st
*** 3400,3425 ****
return false;
}
- case CONSTRUCTOR:
- {
- /* In this context we know that we are on the RHS of an
- assignment, so CONSTRUCTOR operands are OK. */
- /* FIXME: verify constructor arguments. */
- return false;
- }
-
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in shift expression");
- return true;
- }
-
if (!TREE_CODE (rhs1_type) == INTEGER_TYPE
|| !useless_type_conversion_p (lhs_type, rhs1_type))
{
error ("type mismatch in shift expression");
--- 3443,3455 ----
return false;
}
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
{
if (!TREE_CODE (rhs1_type) == INTEGER_TYPE
+ || !TREE_CODE (rhs2_type) == INTEGER_TYPE
|| !useless_type_conversion_p (lhs_type, rhs1_type))
{
error ("type mismatch in shift expression");
*************** verify_types_in_gimple_assign (gimple st
*** 3432,3459 ****
return false;
}
- case PLUS_EXPR:
- case MINUS_EXPR:
- {
- if (POINTER_TYPE_P (lhs_type)
- || POINTER_TYPE_P (rhs1_type)
- || POINTER_TYPE_P (rhs2_type))
- {
- error ("invalid (pointer) operands to plus/minus");
- return true;
- }
-
- /* Continue with generic binary expression handling. */
- break;
- }
-
case POINTER_PLUS_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in pointer plus expression");
- return true;
- }
if (!POINTER_TYPE_P (rhs1_type)
|| !useless_type_conversion_p (lhs_type, rhs1_type)
|| !useless_type_conversion_p (sizetype, rhs2_type))
--- 3462,3469 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3468,3497 ****
return false;
}
- case ADDR_EXPR:
- {
- tree op = TREE_OPERAND (rhs1, 0);
- if (!is_gimple_addressable (op))
- {
- error ("invalid operand in unary expression");
- return true;
- }
-
- if (!one_pointer_to_useless_type_conversion_p (lhs_type, TREE_TYPE (op))
- /* FIXME: a longstanding wart, &a == &a[0]. */
- && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
- || !one_pointer_to_useless_type_conversion_p (lhs_type,
- TREE_TYPE (TREE_TYPE (op)))))
- {
- error ("type mismatch in address expression");
- debug_generic_stmt (lhs_type);
- debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
- return true;
- }
-
- return verify_types_in_gimple_reference (TREE_OPERAND (rhs1, 0));
- }
-
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
gcc_unreachable ();
--- 3478,3483 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3500,3511 ****
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
{
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in truth expression");
- return true;
- }
-
/* We allow any kind of integral typed argument and result. */
if (!INTEGRAL_TYPE_P (rhs1_type)
|| !INTEGRAL_TYPE_P (rhs2_type)
--- 3486,3491 ----
*************** verify_types_in_gimple_assign (gimple st
*** 3521,3629 ****
return false;
}
! case TRUTH_NOT_EXPR:
{
! if (!is_gimple_val (rhs1))
{
! error ("invalid operand in unary not");
return true;
}
! /* For TRUTH_NOT_EXPR we can have any kind of integral
! typed arguments and results. */
! if (!INTEGRAL_TYPE_P (rhs1_type)
! || !INTEGRAL_TYPE_P (lhs_type))
{
! error ("type mismatch in not expression");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
return true;
}
! return false;
! }
! /* After gimplification we should not have any of these. */
! case ASM_EXPR:
! case BIND_EXPR:
! case CALL_EXPR:
! case COND_EXPR:
! case TREE_LIST:
! case COMPOUND_EXPR:
! case MODIFY_EXPR:
! case INIT_EXPR:
! case GOTO_EXPR:
! case LABEL_EXPR:
! case RETURN_EXPR:
! case TRY_FINALLY_EXPR:
! case TRY_CATCH_EXPR:
! case EH_FILTER_EXPR:
! case STATEMENT_LIST:
! {
! error ("tree node that should already be gimple.");
! return true;
}
case OBJ_TYPE_REF:
/* FIXME. */
! return false;
default:;
}
! /* Generic handling via classes. */
! switch (TREE_CODE_CLASS (rhs_code))
! {
! case tcc_exceptional: /* for SSA_NAME */
! case tcc_unary:
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
! break;
! case tcc_binary:
! if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
! {
! error ("invalid operands in binary expression");
! return true;
! }
! if (!useless_type_conversion_p (lhs_type, rhs1_type)
! || !useless_type_conversion_p (lhs_type, rhs2_type))
! {
! error ("type mismatch in binary expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (rhs1_type);
! debug_generic_stmt (rhs2_type);
! return true;
! }
! break;
! case tcc_reference:
! /* All tcc_reference trees are GIMPLE_SINGLE_RHS. Verify that
! no implicit type change happens here. */
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
! return verify_types_in_gimple_reference (rhs1);
! case tcc_comparison:
! return verify_gimple_comparison (lhs_type, rhs1, rhs2);
! default:;
! }
! return false;
}
-
/* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there
is a problem, otherwise false. */
--- 3501,3709 ----
return false;
}
! case LT_EXPR:
! case LE_EXPR:
! case GT_EXPR:
! case GE_EXPR:
! case EQ_EXPR:
! case NE_EXPR:
! case UNORDERED_EXPR:
! case ORDERED_EXPR:
! case UNLT_EXPR:
! case UNLE_EXPR:
! case UNGT_EXPR:
! case UNGE_EXPR:
! case UNEQ_EXPR:
! case LTGT_EXPR:
! /* Comparisons are also binary, but the result type is not
! connected to the operand types. */
! return verify_gimple_comparison (lhs_type, rhs1, rhs2);
!
! case PLUS_EXPR:
! case MINUS_EXPR:
{
! if (POINTER_TYPE_P (lhs_type)
! || POINTER_TYPE_P (rhs1_type)
! || POINTER_TYPE_P (rhs2_type))
{
! error ("invalid (pointer) operands to plus/minus");
return true;
}
! /* Continue with generic binary expression handling. */
! break;
! }
!
! case MULT_EXPR:
! case TRUNC_DIV_EXPR:
! case CEIL_DIV_EXPR:
! case FLOOR_DIV_EXPR:
! case ROUND_DIV_EXPR:
! case TRUNC_MOD_EXPR:
! case CEIL_MOD_EXPR:
! case FLOOR_MOD_EXPR:
! case ROUND_MOD_EXPR:
! case RDIV_EXPR:
! case EXACT_DIV_EXPR:
! case MIN_EXPR:
! case MAX_EXPR:
! case BIT_IOR_EXPR:
! case BIT_XOR_EXPR:
! case BIT_AND_EXPR:
! case WIDEN_SUM_EXPR:
! case WIDEN_MULT_EXPR:
! case VEC_LSHIFT_EXPR:
! case VEC_RSHIFT_EXPR:
! case VEC_WIDEN_MULT_HI_EXPR:
! case VEC_WIDEN_MULT_LO_EXPR:
! case VEC_PACK_TRUNC_EXPR:
! case VEC_PACK_SAT_EXPR:
! case VEC_PACK_FIX_TRUNC_EXPR:
! case VEC_EXTRACT_EVEN_EXPR:
! case VEC_EXTRACT_ODD_EXPR:
! case VEC_INTERLEAVE_HIGH_EXPR:
! case VEC_INTERLEAVE_LOW_EXPR:
! /* Continue with generic binary expression handling. */
! break;
!
! default:
! gcc_unreachable ();
! }
!
! if (!useless_type_conversion_p (lhs_type, rhs1_type)
! || !useless_type_conversion_p (lhs_type, rhs2_type))
! {
! error ("type mismatch in binary expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (rhs1_type);
! debug_generic_stmt (rhs2_type);
! return true;
! }
!
! return false;
! }
!
! /* Verify a gimple assignment statement STMT with a single rhs.
! Returns true if anything is wrong. */
!
! static bool
! verify_gimple_assign_single (gimple stmt)
! {
! enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
! tree lhs = gimple_assign_lhs (stmt);
! tree lhs_type = TREE_TYPE (lhs);
! tree rhs1 = gimple_assign_rhs1 (stmt);
! tree rhs1_type = TREE_TYPE (rhs1);
! bool res = false;
!
! if (!useless_type_conversion_p (lhs_type, rhs1_type))
! {
! error ("non-trivial conversion at assignment");
! debug_generic_expr (lhs_type);
! debug_generic_expr (rhs1_type);
! return true;
! }
!
! if (handled_component_p (lhs))
! res |= verify_types_in_gimple_reference (lhs);
!
! /* Special codes we cannot handle via their class. */
! switch (rhs_code)
! {
! case ADDR_EXPR:
! {
! tree op = TREE_OPERAND (rhs1, 0);
! if (!is_gimple_addressable (op))
{
! error ("invalid operand in unary expression");
return true;
}
! if (!one_pointer_to_useless_type_conversion_p (lhs_type, TREE_TYPE (op))
! /* FIXME: a longstanding wart, &a == &a[0]. */
! && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
! || !one_pointer_to_useless_type_conversion_p (lhs_type,
! TREE_TYPE (TREE_TYPE (op)))))
! {
! error ("type mismatch in address expression");
! debug_generic_stmt (lhs_type);
! debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
! return true;
! }
! return verify_types_in_gimple_reference (op);
}
+ /* tcc_reference */
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case TARGET_MEM_REF:
+ return res || verify_types_in_gimple_reference (rhs1);
+
+ /* tcc_constant */
+ case SSA_NAME:
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ case STRING_CST:
+ /* tcc_declaration */
+ case VAR_DECL:
+ case CONST_DECL:
+ case PARM_DECL:
+ return res;
+
+ case COND_EXPR:
+ case CONSTRUCTOR:
case OBJ_TYPE_REF:
+ case ASSERT_EXPR:
+ case WITH_SIZE_EXPR:
+ case EXC_PTR_EXPR:
+ case FILTER_EXPR:
+ case POLYNOMIAL_CHREC:
+ case DOT_PROD_EXPR:
+ case VEC_COND_EXPR:
+ case REALIGN_LOAD_EXPR:
/* FIXME. */
! return res;
default:;
}
! return res;
! }
! /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
! is a problem, otherwise false. */
! static bool
! verify_gimple_assign (gimple stmt)
! {
! switch (gimple_assign_rhs_class (stmt))
! {
! case GIMPLE_SINGLE_RHS:
! return verify_gimple_assign_single (stmt);
! case GIMPLE_UNARY_RHS:
! return verify_gimple_assign_unary (stmt);
! case GIMPLE_BINARY_RHS:
! return verify_gimple_assign_binary (stmt);
! default:
! gcc_unreachable ();
! }
}
/* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there
is a problem, otherwise false. */
*************** verify_types_in_gimple_stmt (gimple stmt
*** 3758,3764 ****
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
! return verify_types_in_gimple_assign (stmt);
case GIMPLE_LABEL:
return TREE_CODE (gimple_label_label (stmt)) != LABEL_DECL;
--- 3838,3844 ----
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
! return verify_gimple_assign (stmt);
case GIMPLE_LABEL:
return TREE_CODE (gimple_label_label (stmt)) != LABEL_DECL;
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def 2008-09-04 13:49:18.000000000 +0200
--- trunk/gcc/tree.def 2008-09-04 13:50:38.000000000 +0200
*************** DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "v
*** 1137,1143 ****
outcome (0 for not taken and 1 for taken). Once the profile is guessed
all conditional branches leading to execution paths executing the
PREDICT_EXPR will get predicted by the specified predictor. */
! DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_unary, 1)
/* OPTIMIZATION_NODE. Node to store the optimization options. */
DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
--- 1137,1143 ----
outcome (0 for not taken and 1 for taken). Once the profile is guessed
all conditional branches leading to execution paths executing the
PREDICT_EXPR will get predicted by the specified predictor. */
! DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_expression, 1)
/* OPTIMIZATION_NODE. Node to store the optimization options. */
DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
Index: trunk/gcc/gimplify.c
===================================================================
*** trunk.orig/gcc/gimplify.c 2008-09-04 13:49:18.000000000 +0200
--- trunk/gcc/gimplify.c 2008-09-04 15:07:36.000000000 +0200
*************** gimplify_conversion (tree *expr_p)
*** 1872,1877 ****
--- 1872,1883 ----
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;
}
*************** gimplify_addr_expr (tree *expr_p, gimple
*** 4555,4574 ****
/* 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);
! /* 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;
}
--- 4561,4591 ----
/* Mark the RHS addressable. */
ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
is_gimple_addressable, fb_either);
! if (ret == GS_ERROR)
! break;
! /* 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);
!
! op0 = 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;
}
Index: trunk/gcc/testsuite/g++.dg/torture/pr37354.C
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/g++.dg/torture/pr37354.C 2008-09-04 13:50:38.000000000 +0200
***************
*** 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);
+ }
+
Index: trunk/gcc/fortran/trans-expr.c
===================================================================
*** trunk.orig/gcc/fortran/trans-expr.c 2008-09-01 11:00:19.000000000 +0200
--- trunk/gcc/fortran/trans-expr.c 2008-09-04 14:43:09.000000000 +0200
*************** gfc_conv_missing_dummy (gfc_se * se, gfc
*** 161,167 ****
tmp = fold_convert (tmp, build_fold_indirect_ref (se->expr));
/* Test for a NULL value. */
! tmp = build3 (COND_EXPR, TREE_TYPE (tmp), present, tmp, integer_one_node);
tmp = gfc_evaluate_now (tmp, &se->pre);
se->expr = build_fold_addr_expr (tmp);
}
--- 161,168 ----
tmp = fold_convert (tmp, build_fold_indirect_ref (se->expr));
/* Test for a NULL value. */
! tmp = build3 (COND_EXPR, TREE_TYPE (tmp), present, tmp,
! fold_convert (TREE_TYPE (tmp), integer_one_node));
tmp = gfc_evaluate_now (tmp, &se->pre);
se->expr = build_fold_addr_expr (tmp);
}
Index: trunk/gcc/cp/rtti.c
===================================================================
*** trunk.orig/gcc/cp/rtti.c 2008-08-01 11:10:34.000000000 +0200
--- trunk/gcc/cp/rtti.c 2008-09-04 15:58:27.000000000 +0200
*************** build_dynamic_cast_1 (tree type, tree ex
*** 722,728 ****
result = save_expr (result);
neq = c_common_truthvalue_conversion (result);
! return build3 (COND_EXPR, type, neq, result, bad);
}
/* Now back to the type we want from a void*. */
--- 722,730 ----
result = save_expr (result);
neq = c_common_truthvalue_conversion (result);
! return cp_convert (type,
! build3 (COND_EXPR, TREE_TYPE (result),
! neq, result, bad));
}
/* Now back to the type we want from a void*. */
Index: trunk/gcc/fortran/trans-array.c
===================================================================
*** trunk.orig/gcc/fortran/trans-array.c 2008-08-27 16:57:06.000000000 +0200
--- trunk/gcc/fortran/trans-array.c 2008-09-04 16:06:15.000000000 +0200
*************** gfc_conv_array_parameter (gfc_se * se, g
*** 5250,5257 ****
if (fsym && fsym->attr.optional && sym && sym->attr.optional)
{
tmp = gfc_conv_expr_present (sym);
! ptr = build3 (COND_EXPR, TREE_TYPE (se->expr), tmp, ptr,
! null_pointer_node);
}
ptr = gfc_evaluate_now (ptr, &se->pre);
--- 5250,5258 ----
if (fsym && fsym->attr.optional && sym && sym->attr.optional)
{
tmp = gfc_conv_expr_present (sym);
! ptr = build3 (COND_EXPR, TREE_TYPE (se->expr), tmp,
! fold_convert (TREE_TYPE (se->expr), ptr),
! fold_convert (TREE_TYPE (se->expr), null_pointer_node));
}
ptr = gfc_evaluate_now (ptr, &se->pre);
Index: trunk/gcc/fortran/trans-intrinsic.c
===================================================================
*** trunk.orig/gcc/fortran/trans-intrinsic.c 2008-09-04 13:49:18.000000000 +0200
--- trunk/gcc/fortran/trans-intrinsic.c 2008-09-04 16:23:15.000000000 +0200
*************** gfc_conv_intrinsic_merge (gfc_se * se, g
*** 2918,2924 ****
se->string_length = len;
}
type = TREE_TYPE (tsource);
! se->expr = fold_build3 (COND_EXPR, type, mask, tsource, fsource);
}
--- 2918,2925 ----
se->string_length = len;
}
type = TREE_TYPE (tsource);
! se->expr = fold_build3 (COND_EXPR, type, mask, tsource,
! fold_convert (type, fsource));
}
Index: trunk/gcc/testsuite/gfortran.dg/internal_pack_4.f90
===================================================================
*** trunk.orig/gcc/testsuite/gfortran.dg/internal_pack_4.f90 2008-07-29 11:47:17.000000000 +0200
--- trunk/gcc/testsuite/gfortran.dg/internal_pack_4.f90 2008-09-04 16:08:23.000000000 +0200
*************** USE M1
*** 26,31 ****
CALL S2()
END
! ! { dg-final { scan-tree-dump-times "a != 0B \\? _gfortran_internal_pack" 1 "original" } }
! { dg-final { scan-tree-dump-times "if \\(a != 0B &&" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
--- 26,31 ----
CALL S2()
END
! ! { dg-final { scan-tree-dump-times "a != 0B \\? \\\(.*\\\) _gfortran_internal_pack" 1 "original" } }
! { dg-final { scan-tree-dump-times "if \\(a != 0B &&" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
More information about the Fortran
mailing list