tree prom_type;
tree prom_type = NULL_TREE;
patch_binop (node, wfl_op1, wfl_op2)     tree node;     tree wfl_op1;     tree wfl_op2;{  tree op1 = TREE_OPERAND (node, 0);  tree op2 = TREE_OPERAND (node, 1);  tree op1_type = TREE_TYPE (op1);  tree op2_type = TREE_TYPE (op2);  tree prom_type;  int code = TREE_CODE (node);  /* If 1, tell the routine that we have to return error_mark_node     after checking for the initialization of the RHS */  int error_found = 0;  EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);  switch (code)    {    /* 15.16 Multiplicative operators */    case MULT_EXPR:		/* 15.16.1 Multiplication Operator * */    case RDIV_EXPR:		/* 15.16.2 Division Operator / */    case TRUNC_MOD_EXPR:	/* 15.16.3 Remainder operator % */      if (!JPRIMITIVE_TYPE_P (op1_type) || !JPRIMITIVE_TYPE_P (op2_type))	{	  if (!JPRIMITIVE_TYPE_P (op1_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op1_type);	  if (!JPRIMITIVE_TYPE_P (op2_type) && (op1_type != op2_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op2_type);	  TREE_TYPE (node) = error_mark_node;	  error_found = 1;	  break;	}      prom_type = binary_numeric_promotion (op1_type, op2_type, &op1, &op2);      /* Change the division operator if necessary */      if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)	TREE_SET_CODE (node, TRUNC_DIV_EXPR);      /* This one is more complicated. FLOATs are processed by a	 function call to soft_fmod. Duplicate the value of the	 COMPOUND_ASSIGN_P flag. */      if (code == TRUNC_MOD_EXPR)	{	  tree mod = build_java_binop (TRUNC_MOD_EXPR, prom_type, op1, op2);	  COMPOUND_ASSIGN_P (mod) = COMPOUND_ASSIGN_P (node);	  TREE_SIDE_EFFECTS (mod)	    = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);	  return mod;	}      break;    /* 15.17 Additive Operators */    case PLUS_EXPR:		/* 15.17.1 String Concatenation Operator + */      /* Operation is valid if either one argument is a string	 constant, a String object or a StringBuffer crafted for the	 purpose of the a previous usage of the String concatenation	 operator */      if (TREE_CODE (op1) == STRING_CST 	  || TREE_CODE (op2) == STRING_CST	  || JSTRING_TYPE_P (op1_type)	  || JSTRING_TYPE_P (op2_type)	  || IS_CRAFTED_STRING_BUFFER_P (op1)	  || IS_CRAFTED_STRING_BUFFER_P (op2))	return build_string_concatenation (op1, op2);    case MINUS_EXPR:		/* 15.17.2 Additive Operators (+ and -) for				   Numeric Types */      if (!JPRIMITIVE_TYPE_P (op1_type) || !JPRIMITIVE_TYPE_P (op2_type))	{	  if (!JPRIMITIVE_TYPE_P (op1_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op1_type);	  if (!JPRIMITIVE_TYPE_P (op2_type) && (op1_type != op2_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op2_type);	  TREE_TYPE (node) = error_mark_node;	  error_found = 1;	  break;	}      prom_type = binary_numeric_promotion (op1_type, op2_type, &op1, &op2);      break;    /* 15.18 Shift Operators */    case LSHIFT_EXPR:    case RSHIFT_EXPR:    case URSHIFT_EXPR:      if (!JINTEGRAL_TYPE_P (op1_type) || !JINTEGRAL_TYPE_P (op2_type))	{	  if (!JINTEGRAL_TYPE_P (op1_type))	    ERROR_CAST_NEEDED_TO_INTEGRAL (wfl_operator, node, op1_type);	  else	    parse_error_context 	      (wfl_operator, (JPRIMITIVE_TYPE_P (op2_type) ? 	       "Incompatible type for `%s'. Explicit cast needed to convert "	       "shift distance from `%s' to integral" : 	       "Incompatible type for `%s'. Can't convert shift distance from "	       "`%s' to integral"), 	       operator_string (node), lang_printable_name (op2_type, 0));	  TREE_TYPE (node) = error_mark_node;	  error_found = 1;	  break;	}      /* Unary numeric promotion (5.6.1) is performed on each operand         separatly */      op1 = do_unary_numeric_promotion (op1);      op2 = do_unary_numeric_promotion (op2);      /* The type of the shift expression is the type of the promoted         type of the left-hand operand */      prom_type = TREE_TYPE (op1);      /* Shift int only up to 0x1f and long up to 0x3f */      if (prom_type == int_type_node)	op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, 			   build_int_2 (0x1f, 0)));      else	op2 = fold (build (BIT_AND_EXPR, int_type_node, op2, 			   build_int_2 (0x3f, 0)));      /* The >>> operator is a >> operating on unsigned quantities */      if (code == URSHIFT_EXPR && ! flag_emit_class_files)	{	  tree to_return;          tree utype = unsigned_type (prom_type);          op1 = convert (utype, op1);	  TREE_SET_CODE (node, RSHIFT_EXPR);          TREE_OPERAND (node, 0) = op1;          TREE_OPERAND (node, 1) = op2;          TREE_TYPE (node) = utype;	  to_return = convert (prom_type, node);	  /* Copy the original value of the COMPOUND_ASSIGN_P flag */	  COMPOUND_ASSIGN_P (to_return) = COMPOUND_ASSIGN_P (node);	  TREE_SIDE_EFFECTS (to_return)	    = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);	  return to_return;	}      break;      /* 15.19.1 Type Comparison Operator instaceof */    case INSTANCEOF_EXPR:      TREE_TYPE (node) = boolean_type_node;      if (!(op2_type = resolve_type_during_patch (op2)))	return error_mark_node;      /* The first operand must be a reference type or the null type */      if (!JREFERENCE_TYPE_P (op1_type) && op1 != null_pointer_node)	error_found = 1;	/* Error reported further below */      /* The second operand must be a reference type */      if (!JREFERENCE_TYPE_P (op2_type))	{	  SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);	  parse_error_context	    (wfl_operator, "Invalid argument `%s' for `instanceof'",	     lang_printable_name (op2_type, 0));	  error_found = 1;	}      if (!error_found && valid_ref_assignconv_cast_p (op1_type, op2_type, 1))	{	  /* If the first operand is null, the result is always false */	  if (op1 == null_pointer_node)	    return boolean_false_node;	  else if (flag_emit_class_files)	    {	      TREE_OPERAND (node, 1) = op2_type;	      TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1);	      return node;	    }	  /* Otherwise we have to invoke instance of to figure it out */	  else	    {	      tree call =		build (CALL_EXPR, boolean_type_node,		       build_address_of (soft_instanceof_node),		       tree_cons 		       (NULL_TREE, op1,			build_tree_list (NULL_TREE,					 build_class_ref (op2_type))),		       NULL_TREE);	      TREE_SIDE_EFFECTS (call) = TREE_SIDE_EFFECTS (op1);	      return call;	    }	}      /* There is no way the expression operand can be an instance of	 the type operand. This is a compile time error. */      else	{	  char *t1 = strdup (lang_printable_name (op1_type, 0));	  SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);	  parse_error_context 	    (wfl_operator, "Impossible for `%s' to be instance of `%s'",	     t1, lang_printable_name (op2_type, 0));	  free (t1);	  error_found = 1;	}            break;      /* 15.21 Bitwise and Logical Operators */    case BIT_AND_EXPR:    case BIT_XOR_EXPR:    case BIT_IOR_EXPR:      if (JINTEGRAL_TYPE_P (op1_type) && JINTEGRAL_TYPE_P (op2_type))	/* Binary numeric promotion is performed on both operand and the	   expression retain that type */	prom_type = binary_numeric_promotion (op1_type, op2_type, &op1, &op2);      else if (TREE_CODE (op1_type) == BOOLEAN_TYPE 	       && TREE_CODE (op1_type) == BOOLEAN_TYPE)	/* The type of the bitwise operator expression is BOOLEAN */	prom_type = boolean_type_node;      else	{	  if (!JINTEGRAL_TYPE_P (op1_type))	    ERROR_CAST_NEEDED_TO_INTEGRAL (wfl_operator, node, op1_type);	  if (!JINTEGRAL_TYPE_P (op2_type) && (op1_type != op2_type))	    ERROR_CAST_NEEDED_TO_INTEGRAL (wfl_operator, node, op2_type);	  TREE_TYPE (node) = error_mark_node;	  error_found = 1;	  /* Insert a break here if adding thing before the switch's             break for this case */	}      break;      /* 15.22 Conditional-And Operator */    case TRUTH_ANDIF_EXPR:      /* 15.23 Conditional-Or Operator */    case TRUTH_ORIF_EXPR:      /* Operands must be of BOOLEAN type */      if (TREE_CODE (op1_type) != BOOLEAN_TYPE || 	  TREE_CODE (op2_type) != BOOLEAN_TYPE)	{	  if (TREE_CODE (op1_type) != BOOLEAN_TYPE)	    ERROR_CANT_CONVERT_TO_BOOLEAN (wfl_operator, node, op1_type);	  if (TREE_CODE (op2_type) != BOOLEAN_TYPE && (op1_type != op2_type))	    ERROR_CANT_CONVERT_TO_BOOLEAN (wfl_operator, node, op2_type);	  TREE_TYPE (node) = boolean_type_node;	  error_found = 1;	  break;	}      /* The type of the conditional operators is BOOLEAN */      prom_type = boolean_type_node;      break;      /* 15.19.1 Numerical Comparison Operators <, <=, >, >= */    case LT_EXPR:    case GT_EXPR:    case LE_EXPR:    case GE_EXPR:      /* The type of each of the operands must be a primitive numeric         type */      if (!JNUMERIC_TYPE_P (op1_type) || ! JNUMERIC_TYPE_P (op2_type))	{	  if (!JNUMERIC_TYPE_P (op1_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op1_type);	  if (!JNUMERIC_TYPE_P (op2_type) && (op1_type != op2_type))	    ERROR_CANT_CONVERT_TO_NUMERIC (wfl_operator, node, op2_type);	  TREE_TYPE (node) = boolean_type_node;	  error_found = 1;	  break;	}      /* Binary numeric promotion is performed on the operands */      binary_numeric_promotion (op1_type, op2_type, &op1, &op2);      /* The type of the relation expression is always BOOLEAN */      prom_type = boolean_type_node;      break;      /* 15.20 Equality Operator */    case EQ_EXPR:    case NE_EXPR:      /* 15.20.1 Numerical Equality Operators == and != */      /* Binary numeric promotion is performed on the operands */      if (JNUMERIC_TYPE_P (op1_type) && JNUMERIC_TYPE_P (op2_type))	binary_numeric_promotion (op1_type, op2_type, &op1, &op2);            /* 15.20.2 Boolean Equality Operators == and != */      else if (TREE_CODE (op1_type) == BOOLEAN_TYPE &&	  TREE_CODE (op2_type) == BOOLEAN_TYPE)	;			/* Nothing to do here */            /* 15.20.3 Reference Equality Operators == and != */      /* Types have to be either references or the null type. If         they're references, it must be possible to convert either         type to the other by casting conversion. */      else if (op1 == null_pointer_node || op2 == null_pointer_node 	       || (JREFERENCE_TYPE_P (op1_type) && JREFERENCE_TYPE_P (op2_type)		   && (valid_ref_assignconv_cast_p (op1_type, op2_type, 1)		       || valid_ref_assignconv_cast_p (op2_type, 						       op1_type, 1))))	;			/* Nothing to do here */	        /* Else we have an error figure what can't be converted into	 what and report the error */      else	{	  char *t1;	  t1 = strdup (lang_printable_name (op1_type, 0));	  parse_error_context 	    (wfl_operator, "Incompatible type for `%s'. Can't convert `%s' "	     "to `%s'", operator_string (node), t1, 	     lang_printable_name (op2_type, 0));	  free (t1);	  TREE_TYPE (node) = boolean_type_node;	  error_found = 1;	  break;	}      prom_type = boolean_type_node;      break;    }  if (error_found)    return error_mark_node;  TREE_OPERAND (node, 0) = op1;  TREE_OPERAND (node, 1) = op2;  TREE_TYPE (node) = prom_type;  TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (op1) | TREE_SIDE_EFFECTS (op2);    if (flag_emit_xref)    return node;  /* fold does not respect side-effect order as required for Java but not C.   * Also, it sometimes create SAVE_EXPRs which are bad when emitting   * bytecode.   */  if (flag_emit_class_files ? (TREE_CONSTANT (op1) && TREE_CONSTANT (op2))      : ! TREE_SIDE_EFFECTS (node))    node = fold (node);  return node;}