This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] A GIMPLE and GIMPLE type system verifier


This is the second post of the gimple (type) verifier.  With this
patch applied I can bootstrap all languages
(--enable-languages=all,ada,treelang,obj-c++ -- tell me if I forgot one)
on x86_64-unknown-linux (with building multilibs where supported).

There are a few testsuite regressions due to the verifier, notably
in the C parts:

FAIL: gcc.dg/debug/redecl-2.c -gdwarf-21 (test for excess errors)
(and variants)
error: non-trivial conversion at assignment^M
int[5] *^M
int[10] *^M
ap = &array10^M

FAIL: gcc.dg/redecl-6.c (test for excess errors)
int[5] *
int[10] *
ap = &array10

these are tricky to resolve as we play games with types here.

In the gfortran parts:

FAIL: gfortran.dg/achar_4.f90  -O0  (test for excess errors)
(and variantes)
achar_4.f90:8: error: non-trivial conversion at assignment^M
char[1:1]^M
char^M
(*D.1501)[S.23] = D.1519^M

this is reported as PR31608, I'm lost in the deeps of the Fortran FE here.

In the libstdc++ parts:

FAIL: tr1/3_function_objects/function/8.cc (test for excess errors)
functional:1620: error: non-trivial conversion at assignment^M
struct ^M
{^M
  X:: * const __pfn;^M
  long int __delta;^M
} * const *^M
struct ^M
{^M
  X:: * const __pfn;^M
  long int __delta;^M
} * const &^M
__ptr = __ptr.322^M

we'll fix that up.


You will note that I "fix" the present verifier with

        * tree-cfg.c (verify_expr): COND_EXPRs can have any
        integral typed condition.

as we do not properly have boolean_type_node typed (or trivially
convertible to that) trees for all the TRUTH_*_EXPRs and for
tcc_comparison class results.  This way propagation trivially
breaks the check above if I leave it alone.  Maybe this is something
worth to fix, but it certainly was not trivial else I'd have done it
already.

The C frontend and C++ frontend fixes have already beed posted separately
but are included here if you want to play with the patch.

The patch has not yet been exposed to code other than GCC and its 
testsuite itself.  The posting here is mainly in preparation for any
discussion that may happen at the summit, possibly as part of the
LTO BOF (though that has many topics already).

Thanks,
Richard.

2007-07-13  Richard Guenther  <rguenther@suse.de>

	* tree-cfg.c (verify_expr): COND_EXPRs can have any
	integral typed condition.
	(verify_gimple_unary_expr, verify_gimple_binary_expr,
	verify_gimple_min_lval, verify_gimple_reference, verify_gimple_expr,
	verify_gimple_modify_stmt, verify_gimple_stmt, verify_gimple_1,
	verify_gimple): New functions.
	* tree-flow.h (verify_gimple): Declare.
	(verify_gimple_1): Declare.
	* gimplify.c (cpt_same_type): Remove.
	(gimplify_addr_expr): Remove checking code.
	(check_pointer_types_r): Remove.
	(gimplify_body): Call verify_gimple_1 instead of check_pointer_types_r.
	Only verify if there were no errors.

	* tree-ssa.c (useless_type_conversion_p): Do not preserve
	booleanness.  Only preserve conversions from a non-base
	type to a base type, not in general between types with
	different TYPE_MIN_VALUE or TYPE_MAX_VALUE.
	* tree-def.c (COND_EXPR): Document that the condition
	can be of any integral type.

        * c-typeck.c (convert_for_assignment): Use the type of
        the member for the initialization.

	cp/
        * call.c (build_new_method_call): Convert initializer to
        the basetype.
        * init.c (build_aggr_init): Do not fiddle with types.
        (build_vec_delete_1): Use correct type for POINTER_PLUS_EXPR.
        * except.c (build_throw): Do not drop qualifiers for the
        pointer type.
        * typeck.c (get_member_function_from_ptrfunc): Do not
        fiddle with types, instead convert.
        (build_ptrmemfunc1): Convert to the target type for
        initialization.
        (gfc_trans_allocate): Convert result to target type.

	treelang/
	* treetree.c (tree_code_generate_return): RETURN_EXPRs
	have volatile type.


Index: gcc/tree-cfg.c
===================================================================
*** gcc.orig/tree-cfg.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/tree-cfg.c	2007-07-13 13:22:49.000000000 +0200
*************** verify_expr (tree *tp, int *walk_subtree
*** 3201,3209 ****
  
      case COND_EXPR:
        x = COND_EXPR_COND (t);
!       if (TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE)
  	{
! 	  error ("non-boolean used in condition");
  	  return x;
  	}
        if (!is_gimple_condexpr (x))
--- 3201,3209 ----
  
      case COND_EXPR:
        x = COND_EXPR_COND (t);
!       if (!INTEGRAL_TYPE_P (TREE_TYPE (x)))
  	{
! 	  error ("non-integral used in condition");
  	  return x;
  	}
        if (!is_gimple_condexpr (x))
*************** verify_expr (tree *tp, int *walk_subtree
*** 3346,3351 ****
--- 3346,4056 ----
  #undef CHECK_OP
  }
  
+ /* Verifies if EXPR is a valid GIMPLE unary expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_unary_expr (tree expr)
+ {
+   tree op = TREE_OPERAND (expr, 0);
+   tree type = TREE_TYPE (expr);
+ 
+   if (!is_gimple_val (op))
+     {
+       error ("invalid operand in unary expression");
+       return true;
+     }
+ 
+   /* For general unary expressions we have the operantions type
+      as the effective type the operation is carried out on.  So all
+      we need to require is that the operand is trivially convertible
+      to that type.  */
+   if (!useless_type_conversion_p (type, TREE_TYPE (op)))
+     {
+       error ("type mismatch in unary expression");
+       debug_generic_expr (type);
+       debug_generic_expr (TREE_TYPE (op));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verifies if EXPR is a valid GIMPLE binary expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_binary_expr (tree expr)
+ {
+   tree op0 = TREE_OPERAND (expr, 0);
+   tree op1 = TREE_OPERAND (expr, 1);
+   tree type = TREE_TYPE (expr);
+ 
+   if (!is_gimple_val (op0) || !is_gimple_val (op1))
+     {
+       error ("invalid operands in binary expression");
+       return true;
+     }
+ 
+   /* For general binary expressions we have the operantions type
+      as the effective type the operation is carried out on.  So all
+      we need to require is that both operands are trivially convertible
+      to that type.  */
+   if (!useless_type_conversion_p (type, TREE_TYPE (op0))
+       || !useless_type_conversion_p (type, TREE_TYPE (op1)))
+     {
+       error ("type mismatch in binary expression");
+       debug_generic_stmt (type);
+       debug_generic_stmt (TREE_TYPE (op0));
+       debug_generic_stmt (TREE_TYPE (op1));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify if EXPR is either a GIMPLE ID or a GIMPLE indirect reference.
+    Returns true if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_min_lval (tree expr)
+ {
+   tree op;
+ 
+   if (is_gimple_id (expr))
+     return false;
+ 
+   if (TREE_CODE (expr) != INDIRECT_REF
+       && TREE_CODE (expr) != ALIGN_INDIRECT_REF
+       && TREE_CODE (expr) != MISALIGNED_INDIRECT_REF)
+     {
+       error ("invalid expression for min lvalue");
+       return true;
+     }
+ 
+   op = TREE_OPERAND (expr, 0);
+   if (!is_gimple_val (op))
+     {
+       error ("invalid operand in indirect reference");
+       debug_generic_stmt (op);
+       return true;
+     }
+   if (!useless_type_conversion_p (TREE_TYPE (expr),
+ 				  TREE_TYPE (TREE_TYPE (op))))
+     {
+       error ("type mismatch in indirect reference");
+       debug_generic_stmt (TREE_TYPE (expr));
+       debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+       return true;
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify if EXPR is a valid GIMPLE reference expression.  Returns true
+    if there is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_reference (tree expr)
+ {
+   while (handled_component_p (expr))
+     {
+       tree op = TREE_OPERAND (expr, 0);
+ 
+       if (TREE_CODE (expr) == ARRAY_REF
+ 	  || TREE_CODE (expr) == ARRAY_RANGE_REF)
+ 	{
+ 	  if (!is_gimple_val (TREE_OPERAND (expr, 1))
+ 	      || (TREE_OPERAND (expr, 2)
+ 		  && !is_gimple_val (TREE_OPERAND (expr, 2)))
+ 	      || (TREE_OPERAND (expr, 3)
+ 		  && !is_gimple_val (TREE_OPERAND (expr, 3))))
+ 	    {
+ 	      error ("invalid operands to array reference");
+ 	      debug_generic_stmt (expr);
+ 	      return true;
+ 	    }
+ 	}
+ 
+       /* Verify if the reference array element types are compatible.  */
+       if (TREE_CODE (expr) == ARRAY_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in array reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+       if (TREE_CODE (expr) == ARRAY_RANGE_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (expr)),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in array range reference");
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (expr)));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+ 
+       if ((TREE_CODE (expr) == REALPART_EXPR
+ 	   || TREE_CODE (expr) == IMAGPART_EXPR)
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_TYPE (op))))
+ 	{
+ 	  error ("type mismatch in real/imagpart reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
+ 	  return true;
+ 	}
+ 
+       if (TREE_CODE (expr) == COMPONENT_REF
+ 	  && !useless_type_conversion_p (TREE_TYPE (expr),
+ 					 TREE_TYPE (TREE_OPERAND (expr, 1))))
+ 	{
+ 	  error ("type mismatch in component reference");
+ 	  debug_generic_stmt (TREE_TYPE (expr));
+ 	  debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1)));
+ 	  return true;
+ 	}
+ 
+       /* For VIEW_CONVERT_EXPRs which are allowed here, too, there
+ 	 is nothing to verify.  Gross mismatches at most invoke
+ 	 undefined behavior.  */
+ 
+       expr = op;
+     }
+ 
+   return verify_gimple_min_lval (expr);
+ }
+ 
+ /* Verify the GIMPLE expression EXPR.  Returns true if there is an
+    error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_expr (tree expr)
+ {
+   tree type = TREE_TYPE (expr);
+ 
+   if (is_gimple_val (expr))
+     return false;
+ 
+   /* Special codes we cannot handle via their class.  */
+   switch (TREE_CODE (expr))
+     {
+     case NOP_EXPR:
+     case CONVERT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in conversion");
+ 	    return true;
+ 	  }
+ 
+ 	/* Allow conversions between integral types.  */
+         if (INTEGRAL_TYPE_P (type) == INTEGRAL_TYPE_P (TREE_TYPE (op)))
+ 	  return false;
+ 
+ 	/* Allow conversions between integral types and pointers only if
+ 	   there is no sign or zero extension involved.  */
+ 	if (((POINTER_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (op)))
+ 	     || (POINTER_TYPE_P (TREE_TYPE (op)) && INTEGRAL_TYPE_P (type)))
+ 	    && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op)))
+ 	  return false;
+ 
+ 	/* Allow conversion from integer to offset type and vice versa.  */
+ 	if ((TREE_CODE (type) == OFFSET_TYPE
+ 	     && TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE)
+ 	    || (TREE_CODE (type) == INTEGER_TYPE
+ 		&& TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE))
+ 	  return false;
+ 
+ 	/* Otherwise assert we are converting between types of the
+ 	   same kind.  */
+ 	if (TREE_CODE (type) != TREE_CODE (TREE_TYPE (op)))
+ 	  {
+ 	    error ("invalid types in nop conversion");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case FLOAT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in int to float conversion");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op))
+ 	    || !SCALAR_FLOAT_TYPE_P (type))
+ 	  {
+ 	    error ("invalid types in conversion to floating point");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+         return false;
+       }
+ 
+     case FIX_TRUNC_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    error ("invalid operand in float to int conversion");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (type)
+ 	    || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (op)))
+ 	  {
+ 	    error ("invalid types in conversion to integer");
+ 	    debug_generic_expr (type);
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+         return false;
+       }
+ 
+     case COMPLEX_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in complex expression");
+ 	    return true;
+ 	  }
+ 	if (!TREE_CODE (type) == COMPLEX_TYPE
+ 	    || !(TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+ 	         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)))
+ 	    || !(TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE
+ 	         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (op1)))
+ 	    || !useless_type_conversion_p (TREE_TYPE (type),
+ 					   TREE_TYPE (op0))
+ 	    || !useless_type_conversion_p (TREE_TYPE (type),
+ 					   TREE_TYPE (op1)))
+ 	  {
+ 	    error ("type mismatch in complex expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case CONSTRUCTOR:
+       {
+ 	/* This is used like COMPLEX_EXPR but for vectors.  */
+ 	if (TREE_CODE (type) != VECTOR_TYPE)
+ 	  {
+ 	    error ("constructor not allowed for non-vector types");
+ 	    debug_generic_stmt (type);
+ 	    return true;
+ 	  }
+ 	/* FIXME: verify constructor arguments.  */
+ 	return false;
+       }
+ 
+     case LSHIFT_EXPR:
+     case RSHIFT_EXPR:
+     case LROTATE_EXPR:
+     case RROTATE_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in shift expression");
+ 	    return true;
+ 	  }
+ 	if (!TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE
+ 	    || !useless_type_conversion_p (type, TREE_TYPE (op0)))
+ 	  {
+ 	    error ("type mismatch in shift expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case PLUS_EXPR:
+     case MINUS_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (POINTER_TYPE_P (type)
+ 	    || POINTER_TYPE_P (TREE_TYPE (op0))
+ 	    || POINTER_TYPE_P (TREE_TYPE (op1)))
+ 	  {
+ 	    error ("invalid (pointer) operands to plus/minus");
+ 	    return true;
+ 	  }
+ 	/* Continue with generic binary expression handling.  */
+ 	break;
+       }
+ 
+     case POINTER_PLUS_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+       	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in pointer plus expression");
+ 	    return true;
+ 	  }
+ 	if (!POINTER_TYPE_P (TREE_TYPE (op0))
+ 	    || TREE_CODE (TREE_TYPE (op1)) != INTEGER_TYPE
+ 	    || !useless_type_conversion_p (type, TREE_TYPE (op0))
+ 	    || !useless_type_conversion_p (sizetype, TREE_TYPE (op1)))
+ 	  {
+ 	    error ("type mismatch in pointer plus expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 	return false;
+       }
+ 
+     case COND_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	tree op2 = TREE_OPERAND (expr, 2);
+ 	if ((!is_gimple_val (op1)
+ 	     && TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
+ 	    || (!is_gimple_val (op2)
+ 		&& TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE))
+ 	  {
+ 	    error ("invalid operands in conditional expression");
+ 	    return true;
+ 	  }
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ 	    || (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE
+ 	        && !useless_type_conversion_p (type, TREE_TYPE (op1)))
+ 	    || (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE
+ 	        && !useless_type_conversion_p (type, TREE_TYPE (op2))))
+ 	  {
+ 	    error ("type mismatch in conditional expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    debug_generic_stmt (TREE_TYPE (op2));
+ 	    return true;
+ 	  }
+ 	return verify_gimple_expr (op0);
+       }
+ 
+     case ADDR_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 	tree ptr_type;
+ 	if (!is_gimple_addressable (op))
+ 	  {
+ 	    error ("invalid operand in unary expression");
+ 	    return true;
+ 	  }
+ 	ptr_type = build_pointer_type (TREE_TYPE (op));
+ 	if (!useless_type_conversion_p (type, ptr_type)
+ 	    /* FIXME: a longstanding wart, &a == &a[0].  */
+ 	    && (TREE_CODE (TREE_TYPE (op)) != ARRAY_TYPE
+ 		|| !useless_type_conversion_p (type,
+ 			build_pointer_type (TREE_TYPE (TREE_TYPE (op))))))
+ 	  {
+ 	    error ("type mismatch in address expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (ptr_type);
+ 	    return true;
+ 	  }
+ 
+ 	return verify_gimple_reference (op);
+       }
+ 
+     case TRUTH_ANDIF_EXPR:
+     case TRUTH_ORIF_EXPR:
+     case TRUTH_AND_EXPR:
+     case TRUTH_OR_EXPR:
+     case TRUTH_XOR_EXPR:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 
+       	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in truth expression");
+ 	    return true;
+ 	  }
+ 
+ 	/* We allow any kind of integral typed argument and result.  */
+ 	if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+ 	    || !INTEGRAL_TYPE_P (TREE_TYPE (op1))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in binary truth expression");
+ 	    debug_generic_stmt (type);
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case TRUTH_NOT_EXPR:
+       {
+ 	tree op = TREE_OPERAND (expr, 0);
+ 
+ 	if (!is_gimple_val (op))
+ 	  {
+ 	    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 (TREE_TYPE (op))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in not expression");
+ 	    debug_generic_expr (TREE_TYPE (expr));
+ 	    debug_generic_expr (TREE_TYPE (op));
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
+     case CALL_EXPR:
+       /* FIXME.  This is going to be difficult with non-unit-at-a-time
+ 	 gimplifying.  */
+       return false;
+ 
+     default:;
+     }
+ 
+   /* Generic handling via classes.  */
+   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
+     {
+     case tcc_unary:
+       return verify_gimple_unary_expr (expr);
+ 
+     case tcc_binary:
+       return verify_gimple_binary_expr (expr);
+ 
+     case tcc_reference:
+       return verify_gimple_reference (expr);
+ 
+     case tcc_comparison:
+       {
+ 	tree op0 = TREE_OPERAND (expr, 0);
+ 	tree op1 = TREE_OPERAND (expr, 1);
+ 	if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ 	  {
+ 	    error ("invalid operands in comparison expression");
+ 	    return true;
+ 	  }
+ 	/* For comparisons we do not have the operations type as the
+ 	   effective type the comparison is carried out in.  Instead
+ 	   we require that either the first operand is trivially
+ 	   convertible into the second, or the other way around.
+ 	   The resulting type of a comparison may be any integral type.
+ 	   Because we special-case pointers to void we allow
+ 	   comparisons of pointers with the same mode as well.  */
+ 	if ((!useless_type_conversion_p (TREE_TYPE (op0), TREE_TYPE (op1))
+ 	     && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))
+ 	     && (!POINTER_TYPE_P (TREE_TYPE (op0))
+ 		 || !POINTER_TYPE_P (TREE_TYPE (op1))
+ 		 || TYPE_MODE (TREE_TYPE (op0)) != TYPE_MODE (TREE_TYPE (op1))))
+ 	    || !INTEGRAL_TYPE_P (type))
+ 	  {
+ 	    error ("type mismatch in comparison expression");
+ 	    debug_generic_stmt (TREE_TYPE (expr));
+ 	    debug_generic_stmt (TREE_TYPE (op0));
+ 	    debug_generic_stmt (TREE_TYPE (op1));
+ 	    return true;
+ 	  }
+         break;
+       }
+ 
+     default:
+       gcc_unreachable ();
+     }
+ 
+   return false;
+ }
+ 
+ /* Verify the GIMPLE assignment statement STMT.  Returns true if there
+    is an error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_modify_stmt (tree stmt)
+ {
+   tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+   tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+ 
+   gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
+ 
+   if (!useless_type_conversion_p (TREE_TYPE (lhs),
+ 				  TREE_TYPE (rhs)))
+     {
+       error ("non-trivial conversion at assignment");
+       debug_generic_expr (TREE_TYPE (lhs));
+       debug_generic_expr (TREE_TYPE (rhs));
+       return true;
+     }
+ 
+   /* Loads/stores from/to a variable are ok.  */
+   if ((is_gimple_val (lhs)
+        && is_gimple_variable (rhs))
+       || (is_gimple_val (rhs)
+ 	  && is_gimple_variable (lhs)))
+     return false;
+ 
+   /* Aggregate copies are ok.  */
+   if (!is_gimple_reg_type (TREE_TYPE (lhs))
+       && !is_gimple_reg_type (TREE_TYPE (rhs)))
+     return false;
+ 
+   /* We might get 'loads' from a parameter which is not a gimple value.  */
+   if (TREE_CODE (rhs) == PARM_DECL)
+     return verify_gimple_expr (lhs);
+ 
+   if (!is_gimple_variable (lhs)
+       && verify_gimple_expr (lhs))
+     return true;
+ 
+   if (!is_gimple_variable (rhs)
+       && verify_gimple_expr (rhs))
+     return true;
+ 
+   return false;
+   /*return verify_gimple_expr (rhs) || verify_gimple_expr (lhs);*/
+ }
+ 
+ /* Verify the GIMPLE statement STMT.  Returns true if there is an
+    error, otherwise false.  */
+ 
+ static bool
+ verify_gimple_stmt (tree stmt)
+ {
+   if (!is_gimple_stmt (stmt))
+     {
+       error ("is not a valid GIMPLE statement");
+       return true;
+     }
+ 
+   if (OMP_DIRECTIVE_P (stmt))
+     {
+       /* OpenMP directives are validated by the FE and never operated
+ 	 on by the optimizers.  Furthermore, OMP_FOR may contain
+ 	 non-gimple expressions when the main index variable has had
+ 	 its address taken.  This does not affect the loop itself
+ 	 because the header of an OMP_FOR is merely used to determine
+ 	 how to setup the parallel iteration.  */
+       return false;
+     }
+ 
+   switch (TREE_CODE (stmt))
+     {
+     case GIMPLE_MODIFY_STMT:
+       return verify_gimple_modify_stmt (stmt);
+ 
+     case GOTO_EXPR:
+     case LABEL_EXPR:
+       return false;
+ 
+     case SWITCH_EXPR:
+       if (!is_gimple_val (TREE_OPERAND (stmt, 0)))
+ 	{
+ 	  error ("invalid operand to switch statement");
+ 	  debug_generic_expr (TREE_OPERAND (stmt, 0));
+ 	}
+       return false;
+ 
+     case RETURN_EXPR:
+       {
+ 	tree op = TREE_OPERAND (stmt, 0);
+ 
+ 	if (TREE_CODE (TREE_TYPE (stmt)) != VOID_TYPE)
+ 	  {
+ 	    error ("type error in return expression");
+ 	    return true;
+ 	  }
+ 
+ 	if (op == NULL_TREE
+ 	    || TREE_CODE (op) == RESULT_DECL)
+ 	  return false;
+ 
+ 	return verify_gimple_modify_stmt (op);
+       }
+ 
+     case CALL_EXPR:
+     case COND_EXPR:
+       return verify_gimple_expr (stmt);
+ 
+     case NOP_EXPR:
+     case CHANGE_DYNAMIC_TYPE_EXPR:
+     case ASM_EXPR:
+       return false;
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ /* Verify the GIMPLE statements inside the statement list STMTS.  */
+ 
+ void
+ verify_gimple_1 (tree stmts)
+ {
+   tree_stmt_iterator tsi;
+ 
+   for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
+     {
+       tree stmt = tsi_stmt (tsi);
+ 
+       switch (TREE_CODE (stmt))
+ 	{
+ 	case BIND_EXPR:
+ 	  verify_gimple_1 (BIND_EXPR_BODY (stmt));
+ 	  break;
+ 
+ 	case TRY_CATCH_EXPR:
+ 	case TRY_FINALLY_EXPR:
+ 	  verify_gimple_1 (TREE_OPERAND (stmt, 0));
+ 	  verify_gimple_1 (TREE_OPERAND (stmt, 1));
+ 	  break;
+ 
+ 	case CATCH_EXPR:
+ 	  verify_gimple_1 (CATCH_BODY (stmt));
+ 	  break;
+ 
+ 	case EH_FILTER_EXPR:
+ 	  verify_gimple_1 (EH_FILTER_FAILURE (stmt));
+ 	  break;
+ 
+ 	default:
+ 	  if (verify_gimple_stmt (stmt))
+ 	    debug_generic_expr (stmt);
+ 	}
+     }
+ }
+ 
+ /* Verify the GIMPLE statements inside the current function.  */
+ 
+ void
+ verify_gimple (void)
+ {
+   verify_gimple_1 (BIND_EXPR_BODY (DECL_SAVED_TREE (cfun->decl)));
+ }
  
  /* Verify STMT, return true if STMT is not in GIMPLE form.
     TODO: Implement type checking.  */
Index: gcc/tree-flow.h
===================================================================
*** gcc.orig/tree-flow.h	2007-07-13 11:38:15.000000000 +0200
--- gcc/tree-flow.h	2007-07-13 11:38:56.000000000 +0200
*************** extern void bsi_commit_edge_inserts (voi
*** 753,758 ****
--- 753,760 ----
  extern void notice_special_calls (tree);
  extern void clear_special_calls (void);
  extern void verify_stmts (void);
+ extern void verify_gimple (void);
+ extern void verify_gimple_1 (tree);
  extern tree tree_block_label (basic_block);
  extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
  extern bool tree_duplicate_sese_region (edge, edge, basic_block *, unsigned,
Index: gcc/gimplify.c
===================================================================
*** gcc.orig/gimplify.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/gimplify.c	2007-07-13 11:38:56.000000000 +0200
*************** typedef struct gimple_temp_hash_elt
*** 113,121 ****
  
  /* Forward declarations.  */
  static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
- #ifdef ENABLE_CHECKING
- static bool cpt_same_type (tree a, tree b);
- #endif
  
  /* Mark X addressable.  Unlike the langhook we expect X to be in gimple
     form and we don't do any syntax checking.  */
--- 113,118 ----
*************** gimplify_addr_expr (tree *expr_p, tree *
*** 3986,4004 ****
  	tree t_op00 = TREE_TYPE (op00);
  
          if (!useless_type_conversion_p (t_expr, t_op00))
! 	  {
! #ifdef ENABLE_CHECKING
! 	    tree t_op0 = TREE_TYPE (op0);
! 	    gcc_assert (POINTER_TYPE_P (t_expr)
! 			&& (cpt_same_type (TREE_TYPE (t_expr), t_op0)
! 			    || (TREE_CODE (t_op0) == ARRAY_TYPE
! 				&& cpt_same_type (TREE_TYPE (t_expr),
! 						  TREE_TYPE (t_op0))))
! 			&& POINTER_TYPE_P (t_op00)
! 			&& cpt_same_type (t_op0, TREE_TYPE (t_op00)));
! #endif
! 	    op00 = fold_convert (TREE_TYPE (expr), op00);
! 	  }
          *expr_p = op00;
          ret = GS_OK;
        }
--- 3983,3989 ----
  	tree t_op00 = TREE_TYPE (op00);
  
          if (!useless_type_conversion_p (t_expr, t_op00))
! 	  op00 = fold_convert (TREE_TYPE (expr), op00);
          *expr_p = op00;
          ret = GS_OK;
        }
*************** gimplify_one_sizepos (tree *expr_p, tree
*** 6394,6477 ****
      }
  }
  
- #ifdef ENABLE_CHECKING
- /* Compare types A and B for a "close enough" match.  */
- 
- static bool
- cpt_same_type (tree a, tree b)
- {
-   if (useless_type_conversion_p (a, b))
-     return true;
- 
-   /* ??? The C++ FE decomposes METHOD_TYPES to FUNCTION_TYPES and doesn't
-      link them together.  This routine is intended to catch type errors
-      that will affect the optimizers, and the optimizers don't add new
-      dereferences of function pointers, so ignore it.  */
-   if ((TREE_CODE (a) == FUNCTION_TYPE || TREE_CODE (a) == METHOD_TYPE)
-       && (TREE_CODE (b) == FUNCTION_TYPE || TREE_CODE (b) == METHOD_TYPE))
-     return true;
- 
-   /* ??? The C FE pushes type qualifiers after the fact into the type of
-      the element from the type of the array.  See build_unary_op's handling
-      of ADDR_EXPR.  This seems wrong -- if we were going to do this, we
-      should have done it when creating the variable in the first place.
-      Alternately, why aren't the two array types made variants?  */
-   if (TREE_CODE (a) == ARRAY_TYPE && TREE_CODE (b) == ARRAY_TYPE)
-     return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b));
- 
-   /* And because of those, we have to recurse down through pointers.  */
-   if (POINTER_TYPE_P (a) && POINTER_TYPE_P (b))
-     return cpt_same_type (TREE_TYPE (a), TREE_TYPE (b));
- 
-   return false;
- }
- 
- /* Check for some cases of the front end missing cast expressions.
-    The type of a dereference should correspond to the pointer type;
-    similarly the type of an address should match its object.  */
- 
- static tree
- check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- 		       void *data ATTRIBUTE_UNUSED)
- {
-   tree t = *tp;
-   tree ptype, otype, dtype;
- 
-   switch (TREE_CODE (t))
-     {
-     case INDIRECT_REF:
-     case ARRAY_REF:
-       otype = TREE_TYPE (t);
-       ptype = TREE_TYPE (TREE_OPERAND (t, 0));
-       dtype = TREE_TYPE (ptype);
-       gcc_assert (cpt_same_type (otype, dtype));
-       break;
- 
-     case ADDR_EXPR:
-       ptype = TREE_TYPE (t);
-       otype = TREE_TYPE (TREE_OPERAND (t, 0));
-       dtype = TREE_TYPE (ptype);
-       if (!cpt_same_type (dtype, otype))
- 	{
- 	  /* &array is allowed to produce a pointer to the element, rather than
- 	     a pointer to the array type.  We must allow this in order to
- 	     properly represent assigning the address of an array in C into
- 	     pointer to the element type.  */
- 	  gcc_assert (TREE_CODE (otype) == ARRAY_TYPE
- 		      && POINTER_TYPE_P (ptype)
- 		      && cpt_same_type (dtype, TREE_TYPE (otype)));
- 	  break;
- 	}
-       break;
- 
-     default:
-       return NULL_TREE;
-     }
- 
- 
-   return NULL_TREE;
- }
- #endif
  
  /* Gimplify the body of statements pointed to by BODY_P.  FNDECL is the
     function decl containing BODY.  */
--- 6379,6384 ----
*************** gimplify_body (tree *body_p, tree fndecl
*** 6541,6547 ****
    gcc_assert (gimplify_ctxp == NULL);
  
  #ifdef ENABLE_CHECKING
!   walk_tree (body_p, check_pointer_types_r, NULL, NULL);
  #endif
  
    timevar_pop (TV_TREE_GIMPLIFY);
--- 6448,6455 ----
    gcc_assert (gimplify_ctxp == NULL);
  
  #ifdef ENABLE_CHECKING
!   if (!errorcount && !sorrycount)
!     verify_gimple_1 (BIND_EXPR_BODY (*body_p));
  #endif
  
    timevar_pop (TV_TREE_GIMPLIFY);
Index: gcc/tree-ssa.c
===================================================================
*** gcc.orig/tree-ssa.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/tree-ssa.c	2007-07-13 11:38:56.000000000 +0200
*************** useless_type_conversion_p (tree outer_ty
*** 940,962 ****
  	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
  	return false;
  
!       /* Preserve booleanness.  Some code assumes an invariant that boolean
! 	 types stay boolean and do not become 1-bit bit-field types.  */
!       if ((TREE_CODE (inner_type) == BOOLEAN_TYPE)
! 	  != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
  	return false;
  
!       /* Preserve changes in the types minimum or maximum value.
! 	 ???  Due to the way we handle sizetype as signed we need
! 	 to jump through hoops here to make sizetype and size_type_node
! 	 compatible.  */
!       if (!tree_int_cst_equal (fold_convert (outer_type,
! 					     TYPE_MIN_VALUE (inner_type)),
! 			       TYPE_MIN_VALUE (outer_type))
! 	  || !tree_int_cst_equal (fold_convert (outer_type,
! 						TYPE_MAX_VALUE (inner_type)),
! 				  TYPE_MAX_VALUE (outer_type)))
! 	return false;
  
        return true;
      }
--- 940,957 ----
  	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
  	return false;
  
!       /* Conversions from a non-base to a base type are not useless.
! 	 This way we preserve the invariant to do arithmetic in
! 	 base types only.  */
!       if (TREE_TYPE (inner_type)
! 	  && TREE_TYPE (inner_type) != inner_type
! 	  && (TREE_TYPE (outer_type) == outer_type
! 	      || TREE_TYPE (outer_type) == NULL_TREE))
  	return false;
  
!       /* We don't need to preserve changes in the types minimum or
! 	 maximum value in general as these do not generate code
! 	 unless the types precisions are different.  */
  
        return true;
      }
Index: gcc/cp/call.c
===================================================================
*** gcc.orig/cp/call.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/cp/call.c	2007-07-13 11:38:56.000000000 +0200
*************** build_new_method_call (tree instance, tr
*** 5503,5508 ****
--- 5503,5515 ----
        name = complete_dtor_identifier;
      }
  
+   if (DECL_CONSTRUCTOR_P (fn))
+     {
+       tree type = build_pointer_type (basetype);
+       if (!same_type_p (type, TREE_TYPE (instance_ptr)))
+ 	instance_ptr = build_nop (type, instance_ptr);
+     }
+ 
    class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
    mem_args = tree_cons (NULL_TREE, instance_ptr, args);
  
Index: gcc/cp/init.c
===================================================================
*** gcc.orig/cp/init.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/cp/init.c	2007-07-13 11:38:56.000000000 +0200
*************** build_aggr_init (tree exp, tree init, in
*** 1135,1141 ****
      /* Just know that we've seen something for this node.  */
      TREE_USED (exp) = 1;
  
-   TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
    is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
    destroy_temps = stmts_are_full_exprs_p ();
    current_stmt_tree ()->stmts_are_full_exprs_p = 0;
--- 1135,1140 ----
*************** build_aggr_init (tree exp, tree init, in
*** 1143,1149 ****
  		      init, LOOKUP_NORMAL|flags);
    stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
    current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
-   TREE_TYPE (exp) = type;
    TREE_READONLY (exp) = was_const;
    TREE_THIS_VOLATILE (exp) = was_volatile;
  
--- 1142,1147 ----
*************** build_vec_delete_1 (tree base, tree maxi
*** 2322,2328 ****
    tbase = create_temporary_var (ptype);
    tbase_init = build_modify_expr (tbase, NOP_EXPR,
  				  fold_build2 (POINTER_PLUS_EXPR, ptype,
! 					       base,
  					       virtual_size));
    DECL_REGISTER (tbase) = 1;
    controller = build3 (BIND_EXPR, void_type_node, tbase,
--- 2320,2326 ----
    tbase = create_temporary_var (ptype);
    tbase_init = build_modify_expr (tbase, NOP_EXPR,
  				  fold_build2 (POINTER_PLUS_EXPR, ptype,
! 					       fold_convert (ptype, base),
  					       virtual_size));
    DECL_REGISTER (tbase) = 1;
    controller = build3 (BIND_EXPR, void_type_node, tbase,
Index: gcc/cp/except.c
===================================================================
*** gcc.orig/cp/except.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/cp/except.c	2007-07-13 11:38:56.000000000 +0200
*************** build_throw (tree exp)
*** 683,689 ****
  	 respectively.  */
        temp_type = is_bitfield_expr_with_lowered_type (exp);
        if (!temp_type)
! 	temp_type = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
  
        /* OK, this is kind of wacky.  The standard says that we call
  	 terminate when the exception handling mechanism, after
--- 683,689 ----
  	 respectively.  */
        temp_type = is_bitfield_expr_with_lowered_type (exp);
        if (!temp_type)
! 	temp_type = type_decays_to (TREE_TYPE (exp));
  
        /* OK, this is kind of wacky.  The standard says that we call
  	 terminate when the exception handling mechanism, after
Index: gcc/c-typeck.c
===================================================================
*** gcc.orig/c-typeck.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/c-typeck.c	2007-07-13 11:38:56.000000000 +0200
*************** convert_for_assignment (tree type, tree 
*** 4028,4033 ****
--- 4028,4034 ----
  	  if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
  	    pedwarn ("ISO C prohibits argument conversion to union type");
  
+ 	  rhs = fold_convert (TREE_TYPE (memb), rhs);
  	  return build_constructor_single (type, memb, rhs);
  	}
      }
Index: gcc/cp/typeck.c
===================================================================
*** gcc.orig/cp/typeck.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/cp/typeck.c	2007-07-13 11:38:56.000000000 +0200
*************** get_member_function_from_ptrfunc (tree *
*** 2649,2655 ****
  	e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
  		     build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1));
  
!       TREE_TYPE (e2) = TREE_TYPE (e3);
        e1 = build_conditional_expr (e1, e2, e3);
  
        /* Make sure this doesn't get evaluated first inside one of the
--- 2649,2655 ----
  	e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
  		     build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1));
  
!       e2 = fold_convert (TREE_TYPE (e3), e2);
        e1 = build_conditional_expr (e1, e2, e3);
  
        /* Make sure this doesn't get evaluated first inside one of the
*************** build_ptrmemfunc1 (tree type, tree delta
*** 6051,6056 ****
--- 6051,6059 ----
    /* Make sure DELTA has the type we want.  */
    delta = convert_and_check (delta_type_node, delta);
  
+   /* Convert to the correct target type if necessary.  */
+   pfn = fold_convert (TREE_TYPE (pfn_field), pfn);
+ 
    /* Finish creating the initializer.  */
    v = VEC_alloc(constructor_elt, gc, 2);
    CONSTRUCTOR_APPEND_ELT(v, pfn_field, pfn);
Index: gcc/tree.def
===================================================================
*** gcc.orig/tree.def	2007-07-13 11:38:15.000000000 +0200
--- gcc/tree.def	2007-07-13 11:38:56.000000000 +0200
*************** DEFTREECODE (TARGET_EXPR, "target_expr",
*** 485,491 ****
     Operand 0 may be of any type.
     Operand 1 must have the same type as the entire expression, unless
     it unconditionally throws an exception, in which case it should
!    have VOID_TYPE.  The same constraints apply to operand 2.  */
  DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3)
  
  /* Vector conditional expression. It is like COND_EXPR, but with
--- 485,492 ----
     Operand 0 may be of any type.
     Operand 1 must have the same type as the entire expression, unless
     it unconditionally throws an exception, in which case it should
!    have VOID_TYPE.  The same constraints apply to operand 2.  The
!    condition in operand 0 must be of integral type.  */
  DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3)
  
  /* Vector conditional expression. It is like COND_EXPR, but with
Index: gcc/treelang/treetree.c
===================================================================
*** gcc.orig/treelang/treetree.c	2007-07-13 11:38:15.000000000 +0200
--- gcc/treelang/treetree.c	2007-07-13 11:38:56.000000000 +0200
*************** tree_code_generate_return (tree type, tr
*** 575,587 ****
                              fold_convert (type, exp));
        TREE_SIDE_EFFECTS (setret) = 1;
        TREE_USED (setret) = 1;
!       setret = build1 (RETURN_EXPR, type, setret);
        /* Use EXPR_LOCUS so we don't lose any information about the file we
  	 are compiling.  */
        SET_EXPR_LOCUS (setret, EXPR_LOCUS (exp));
      }
     else
!      setret = build1 (RETURN_EXPR, type, NULL_TREE);
  
     append_to_statement_list_force (setret, getstmtlist ());
  }
--- 575,587 ----
                              fold_convert (type, exp));
        TREE_SIDE_EFFECTS (setret) = 1;
        TREE_USED (setret) = 1;
!       setret = build1 (RETURN_EXPR, void_type_node, setret);
        /* Use EXPR_LOCUS so we don't lose any information about the file we
  	 are compiling.  */
        SET_EXPR_LOCUS (setret, EXPR_LOCUS (exp));
      }
     else
!      setret = build1 (RETURN_EXPR, void_type_node, NULL_TREE);
  
     append_to_statement_list_force (setret, getstmtlist ());
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]