[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