FreeBSD/contrib/gcc/c-common.c
/* Return a tree for the sum or difference (RESULTCODE says which)
   of pointer PTROP and integer INTOP.  */
Return a tree for the sum or difference (RESULTCODE says which)
of pointer PTROP and integer INTOP.
Return a tree for the sum or difference ( RESULTCODE says which ) of pointer PTROP and integer INTOP .
tree
pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
{
  tree size_exp, ret;
  tree result_type = TREE_TYPE (ptrop);
  if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
    {
      if (pedantic || warn_pointer_arith)
	pedwarn ("pointer of type %<void *%> used in arithmetic");
      size_exp = integer_one_node;
    }
  else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
    {
      if (pedantic || warn_pointer_arith)
	pedwarn ("pointer to a function used in arithmetic");
      size_exp = integer_one_node;
    }
  else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
    {
      if (pedantic || warn_pointer_arith)
	pedwarn ("pointer to member function used in arithmetic");
      size_exp = integer_one_node;
    }
  else
    size_exp = size_in_bytes (TREE_TYPE (result_type));
  fold_defer_overflow_warnings ();
  if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
      && !TREE_CONSTANT (intop)
      && TREE_CONSTANT (TREE_OPERAND (intop, 1))
      && TREE_CONSTANT (size_exp)
      && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
      && (!TYPE_UNSIGNED (TREE_TYPE (intop))
	  || (TYPE_PRECISION (TREE_TYPE (intop))
	      == TYPE_PRECISION (TREE_TYPE (ptrop)))))
    {
      enum tree_code subcode = resultcode;
      tree int_type = TREE_TYPE (intop);
      if (TREE_CODE (intop) == MINUS_EXPR)
	subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
      ptrop = build_binary_op (subcode, ptrop,
			       convert (int_type, TREE_OPERAND (intop, 1)), 1);
      intop = convert (int_type, TREE_OPERAND (intop, 0));
    }
  if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
      || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
    intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
					     TYPE_UNSIGNED (sizetype)), intop);
  intop = convert (result_type,
		   build_binary_op (MULT_EXPR, intop,
				    convert (TREE_TYPE (intop), size_exp), 1));
  ret = fold_build2 (resultcode, result_type, ptrop, intop);
  fold_undefer_and_ignore_overflow_warnings ();
  return ret;
}
tree pointer_int_sum ( enum tree_code resultcode , tree ptrop , tree intop ) { tree size_exp , ret ; tree result_type = TREE_TYPE ( ptrop ) ; if ( TREE_CODE ( TREE_TYPE ( result_type ) ) == VOID_TYPE ) { if ( pedantic || warn_pointer_arith ) pedwarn ( " " ) ; size_exp = integer_one_node ; } else if ( TREE_CODE ( TREE_TYPE ( result_type ) ) == FUNCTION_TYPE ) { if ( pedantic || warn_pointer_arith ) pedwarn ( " " ) ; size_exp = integer_one_node ; } else if ( TREE_CODE ( TREE_TYPE ( result_type ) ) == METHOD_TYPE ) { if ( pedantic || warn_pointer_arith ) pedwarn ( " " ) ; size_exp = integer_one_node ; } else size_exp = size_in_bytes ( TREE_TYPE ( result_type ) ) ; fold_defer_overflow_warnings ( ) ; if ( ( TREE_CODE ( intop ) == PLUS_EXPR || TREE_CODE ( intop ) == MINUS_EXPR ) && ! TREE_CONSTANT ( intop ) && TREE_CONSTANT ( TREE_OPERAND ( intop , 1 ) ) && TREE_CONSTANT ( size_exp ) && TREE_CODE ( TREE_TYPE ( TREE_OPERAND ( intop , 0 ) ) ) == INTEGER_TYPE && ( ! TYPE_UNSIGNED ( TREE_TYPE ( intop ) ) || ( TYPE_PRECISION ( TREE_TYPE ( intop ) ) == TYPE_PRECISION ( TREE_TYPE ( ptrop ) ) ) ) ) { enum tree_code subcode = resultcode ; tree int_type = TREE_TYPE ( intop ) ; if ( TREE_CODE ( intop ) == MINUS_EXPR ) subcode = ( subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR ) ; ptrop = build_binary_op ( subcode , ptrop , convert ( int_type , TREE_OPERAND ( intop , 1 ) ) , 1 ) ; intop = convert ( int_type , TREE_OPERAND ( intop , 0 ) ) ; } if ( TYPE_PRECISION ( TREE_TYPE ( intop ) ) != TYPE_PRECISION ( sizetype ) || TYPE_UNSIGNED ( TREE_TYPE ( intop ) ) != TYPE_UNSIGNED ( sizetype ) ) intop = convert ( c_common_type_for_size ( TYPE_PRECISION ( sizetype ) , TYPE_UNSIGNED ( sizetype ) ) , intop ) ; intop = convert ( result_type , build_binary_op ( MULT_EXPR , intop , convert ( TREE_TYPE ( intop ) , size_exp ) , 1 ) ) ; ret = fold_build2 ( resultcode , result_type , ptrop , intop ) ; fold_undefer_and_ignore_overflow_warnings ( ) ; return ret ; }
Return a tree for the sum or difference (RESULTCODE says which)
of pointer PTROP and integer INTOP.
Return a tree for the sum or difference ( RESULTCODE says which ) of pointer PTROP and integer INTOP .
/* The result is a pointer of the same type that is being added.  */ /* We are manipulating pointer values, so we don't need to warn
     about relying on undefined signed overflow.  We disable the
     warning here because we use integer types so fold won't know that
     they are really pointers.  */ /* If what we are about to multiply by the size of the elements
     contains a constant term, apply distributive law
     and multiply that constant term separately.
     This helps produce common subexpressions.  */ /* If the constant comes from pointer subtraction,
	 skip this optimization--it would cause an error.  */ /* If the constant is unsigned, and smaller than the pointer size,
	 then we must skip this optimization.  This is because it could cause
	 an overflow error if the constant is negative but INTOP is not.  */ /* Convert both subexpression types to the type of intop,
	 because weird cases involving pointer arithmetic
	 can result in a sum or difference with different type args.  */ /* Convert the integer argument to a type the same size as sizetype
     so the multiply won't overflow spuriously.  */ /* Replace the integer argument with a suitable product by the object size.
     Do this multiplication as signed, then convert to the appropriate
     pointer type (actually unsigned integral).  */ /* Create the sum or difference.  */