This is the mail archive of the gdb@sourceware.org mailing list for the GDB 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]

[RFA] BINOP_DIV and ptyp command


Here is a revised patch to
http://sourceware.org/ml/gdb-patches/2008-01/msg00759.html.
- updates for the recent BINOP_EXP changes and fp BINOP_MIN/MAX.
- fixes a small memory leak, blech
- fixes ANSI/ISO-C fp promotion

I can think of a few issues.

1) value_binop still has code in the unsigned case to handle a bit of
   the promotion computation.  This is done in order to properly clip
   the values.  Having all of the code in one place avoids this wart.
   OTOH, having all of the code in one place makes value_binop a bit
   monolithic.  The consistency of having both unop and binop result type
   functions is nice.  OTOH it's only an internal consistency, they're
   all static functions so it's not a strong argument.
   And another way to partition value_binop is along the four major if's,
   e.g. something like.

   if (DECFLOAT)
     return value_binop_decfloat (mumble);
   else if (FLT)
     return value_binop_float (mumble);
   else if (BOOL)
     return value_binop_bool (mumble);
   else /* integer */
     return value_binop_integer (mumble);

2) Another nice thing with having binop_result_type separate is that if
   different languages need to do something differently, there's a
   well-defined place to look.  OTOH, different language requirements may
   not be amenable to partitioning the problem into (1) compute result type,
   (2) compute result.

3) Another nice thing with having binop_result_type separate is that if
   someone else wants to get the result type without values, and only has
   types, {un,bin}op_result_type is there.
   OTOH, if value_binop is really value independent w.r.t. throwing errors,
   then if one really does just want the result type, and only has types as
   inputs, one can construct values on the fly with value_zero,value_one
   and call value_binop.

4) switching on OP in two separate fns is problematic

Tell me what you want to see and I'll update the patch to match.
[And no claim is made that there isn't some higher order issue I'm missing.]

2008-01-30  Doug Evans  <dje@google.com>

	Fix argument promotion for binary arithmetic ops for C.
	* valarith.c (unop_result_type): New fn.
	(binop_result_type): New fn.
	(value_binop): Move result type computation to binop_result_type.
	(value_pos, value_neg, value_complement): Move result type
	computation to unop_result_type.

	* eval.c (evaluate_subexp_standard): Fix type of result of mixed
	integer/float division operations when EVAL_AVOID_SIDE_EFFECTS.
	* valops.c (value_one): New function.
	* value.h (value_one): Declare.

	* gdb.base/whatis-exp.exp: Fix expected result of whatis x+y, x-y,
	x*y, x/y, x%y.

Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.78
diff -u -p -r1.78 eval.c
--- eval.c	30 Jan 2008 07:31:07 -0000	1.78
+++ eval.c	30 Jan 2008 17:11:54 -0000
@@ -1510,12 +1510,31 @@ evaluate_subexp_standard (struct type *e
 	goto nosideret;
       if (binop_user_defined_p (op, arg1, arg2))
 	return value_x_binop (arg1, arg2, op, OP_NULL, noside);
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS
-	       && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD
-		   || op == BINOP_INTDIV))
-	return value_zero (value_type (arg1), not_lval);
       else
-	return value_binop (arg1, arg2, op);
+	{
+	  /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero,
+	     fudge arg2 to avoid division-by-zero, the caller is
+	     (theoretically) only looking for the type of the result.  */
+	  if (noside == EVAL_AVOID_SIDE_EFFECTS
+	      /* ??? Do we really want to test for BINOP_MOD here?
+		 The implementation of value_binop gives it a well-defined
+		 value.  */
+	      && (op == BINOP_DIV
+		  || op == BINOP_INTDIV
+		  || op == BINOP_REM
+		  || op == BINOP_MOD)
+	      && value_logical_not (arg2))
+	    {
+	      struct value *v_one, *retval;
+
+	      v_one = value_one (value_type (arg2), not_lval);
+	      retval = value_binop (arg1, v_one, op);
+	      value_free (v_one);
+	      return retval;
+	    }
+	  else
+	    return value_binop (arg1, arg2, op);
+	}
 
     case BINOP_RANGE:
       arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.56
diff -u -p -r1.56 valarith.c
--- valarith.c	30 Jan 2008 07:28:16 -0000	1.56
+++ valarith.c	30 Jan 2008 17:11:56 -0000
@@ -40,6 +40,9 @@
 #endif
 
 static struct value *value_subscripted_rvalue (struct value *, struct value *, int);
+static struct type *unop_result_type (enum exp_opcode op, struct type *type1);
+static struct type *binop_result_type (enum exp_opcode op, struct type *type1,
+				       struct type *type2);
 
 void _initialize_valarith (void);
 
@@ -742,6 +745,287 @@ value_concat (struct value *arg1, struct
   return (outval);
 }
 
+/* Return result type of OP performed on TYPE1.
+   The result type follows ANSI C rules.
+   If the result is not appropropriate for any particular language then it
+   needs to patch this function to return the correct type.  */
+
+static struct type *
+unop_result_type (enum exp_opcode op, struct type *type1)
+{
+  struct type *result_type;
+
+  type1 = check_typedef (type1);
+  result_type = type1;
+
+  switch (op)
+    {
+    case UNOP_PLUS:
+    case UNOP_NEG:
+      break;
+    case UNOP_COMPLEMENT:
+      /* Reject floats and decimal floats.  */
+      if (!is_integral_type (type1))
+	error (_("Argument to complement operation not an integer or boolean."));
+      break;
+    default:
+      error (_("Invalid unary operation on numbers."));
+    }
+
+  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
+      || TYPE_CODE (type1) == TYPE_CODE_FLT)
+    {
+      return result_type;
+    }
+  else if (is_integral_type (type1))
+    {
+      /* Perform integral promotion for ANSI C/C++.
+	 If not appropropriate for any particular language it needs to
+	 supply its own la_unop_result_type function.  */
+      if (TYPE_LENGTH (type1) < TYPE_LENGTH (builtin_type_int))
+	result_type = builtin_type_int;
+
+      return result_type;
+    }
+  else
+    {
+      error (_("Argument to unary operation not a number."));
+      return 0; /* For lint -- never reached */
+    }
+}
+
+/* Return result type of OP performed on TYPE1, TYPE2.
+   If the result is not appropropriate for any particular language then it
+   needs to patch this function to return the correct type.  */
+
+static struct type *
+binop_result_type (enum exp_opcode op, struct type *type1, struct type *type2)
+{
+  type1 = check_typedef (type1);
+  type2 = check_typedef (type2);
+
+  if ((TYPE_CODE (type1) != TYPE_CODE_FLT
+       && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
+       && !is_integral_type (type1))
+      ||
+      (TYPE_CODE (type2) != TYPE_CODE_FLT
+       && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
+       && !is_integral_type (type2)))
+    error (_("Argument to arithmetic operation not a number or boolean."));
+
+  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
+      || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+    {
+      switch (op)
+	{
+	case BINOP_ADD:
+	case BINOP_SUB:
+	case BINOP_MUL:
+	case BINOP_DIV:
+	case BINOP_EXP:
+	  break;
+	default:
+	  error (_("Operation not valid for decimal floating point number."));
+	}
+
+      if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
+	/* If type1 is not a decimal float, the type of the result is the type
+	   of the decimal float argument, type2.  */
+	return type2;
+      else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
+	/* Same logic, for the case where type2 is not a decimal float.  */
+	return type1;
+      else
+	/* Both are decimal floats, the type of the result is the bigger
+	   of the two.  */
+	return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) ? type1 : type2;
+    }
+  else if (TYPE_CODE (type1) == TYPE_CODE_FLT
+	   || TYPE_CODE (type2) == TYPE_CODE_FLT)
+    {
+      switch (op)
+	{
+	case BINOP_ADD:
+	case BINOP_SUB:
+	case BINOP_MUL:
+	case BINOP_DIV:
+	case BINOP_EXP:
+	case BINOP_MIN:
+	case BINOP_MAX:
+	  break;
+	default:
+	  error (_("Integer-only operation on floating point number."));
+	}
+
+      switch (current_language->la_language)
+	{
+	case language_c:
+	case language_cplus:
+	case language_asm:
+	  /* ??? language_objc? */
+	  /* Perform ANSI/ISO-C promotions.
+	     If only one type is float, use its type.
+	     Otherwise use the bigger type.  */
+	  if (TYPE_CODE (type1) != TYPE_CODE_FLT)
+	    return type2;
+	  else if (TYPE_CODE (type2) != TYPE_CODE_FLT)
+	    return type1;
+	  else
+	    return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) ? type1 : type2;
+
+	default:
+	  /* For other languages the result type is unchanged from 6.7 for
+	     backward compatibility.
+	     If either arg was long double, make sure that value is also long
+	     double.  */
+	  if (TYPE_LENGTH (type1) * 8 > gdbarch_double_bit (current_gdbarch)
+	      || TYPE_LENGTH (type2) * 8 > gdbarch_double_bit (current_gdbarch))
+	    return builtin_type_long_double;
+	  else
+	    return builtin_type_double;
+	}
+    }
+  else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
+	   && TYPE_CODE (type2) == TYPE_CODE_BOOL)
+    {
+      switch (op)
+	{
+	case BINOP_BITWISE_AND:
+	case BINOP_BITWISE_IOR:
+	case BINOP_BITWISE_XOR:
+        case BINOP_EQUAL:
+        case BINOP_NOTEQUAL:
+	  break;
+	default:
+	  error (_("Invalid operation on booleans."));
+	}
+
+      return type1;
+    }
+  else
+    /* Integral operations here.  */
+    /* FIXME: Also mixed integral/booleans, with result an integer.  */
+    {
+      unsigned int promoted_len1 = TYPE_LENGTH (type1);
+      unsigned int promoted_len2 = TYPE_LENGTH (type2);
+      int is_unsigned1 = TYPE_UNSIGNED (type1);
+      int is_unsigned2 = TYPE_UNSIGNED (type2);
+      unsigned int result_len;
+      int unsigned_operation;
+
+      /* Determine type length and signedness after promotion for
+         both operands.  */
+      if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
+	{
+	  is_unsigned1 = 0;
+	  promoted_len1 = TYPE_LENGTH (builtin_type_int);
+	}
+      if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
+	{
+	  is_unsigned2 = 0;
+	  promoted_len2 = TYPE_LENGTH (builtin_type_int);
+	}
+
+      /* Determine type length of the result, and if the operation should
+	 be done unsigned.  For exponentiation and shift operators,
+	 use the length and type of the left operand.  Otherwise,
+	 use the signedness of the operand with the greater length.
+	 If both operands are of equal length, use unsigned operation
+	 if one of the operands is unsigned.  */
+      if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP)
+	{
+	  /* In case of the shift operators and exponentiation the type of
+	     the result only depends on the type of the left operand.  */
+	  unsigned_operation = is_unsigned1;
+	  result_len = promoted_len1;
+	}
+      else if (promoted_len1 > promoted_len2)
+	{
+	  unsigned_operation = is_unsigned1;
+	  result_len = promoted_len1;
+	}
+      else if (promoted_len2 > promoted_len1)
+	{
+	  unsigned_operation = is_unsigned2;
+	  result_len = promoted_len2;
+	}
+      else
+	{
+	  unsigned_operation = is_unsigned1 || is_unsigned2;
+	  result_len = promoted_len1;
+	}
+
+      switch (op)
+	{
+	case BINOP_ADD:
+	case BINOP_SUB:
+	case BINOP_MUL:
+	case BINOP_DIV:
+	case BINOP_INTDIV:
+	case BINOP_EXP:
+	case BINOP_REM:
+	case BINOP_MOD:
+	case BINOP_LSH:
+	case BINOP_RSH:
+	case BINOP_BITWISE_AND:
+	case BINOP_BITWISE_IOR:
+	case BINOP_BITWISE_XOR:
+	case BINOP_LOGICAL_AND:
+	case BINOP_LOGICAL_OR:
+	case BINOP_MIN:
+	case BINOP_MAX:
+	case BINOP_EQUAL:
+	case BINOP_NOTEQUAL:
+	case BINOP_LESS:
+	  break;
+
+	default:
+	  error (_("Invalid binary operation on numbers."));
+	}
+
+      switch (current_language->la_language)
+	{
+	case language_c:
+	case language_cplus:
+	case language_asm:
+	  /* ??? language_objc? */
+	  if (result_len <= TYPE_LENGTH (builtin_type_int))
+	    {
+	      return (unsigned_operation
+		      ? builtin_type_unsigned_int
+		      : builtin_type_int);
+	    }
+	  else if (result_len <= TYPE_LENGTH (builtin_type_long))
+	    {
+	      return (unsigned_operation
+		      ? builtin_type_unsigned_long
+		      : builtin_type_long);
+	    }
+	  else
+	    {
+	      return (unsigned_operation
+		      ? builtin_type_unsigned_long_long
+		      : builtin_type_long_long);
+	    }
+
+	default:
+	  if (unsigned_operation)
+	    {
+	      if (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT)
+		return builtin_type_unsigned_long_long;
+	      else
+		return builtin_type_unsigned_long;
+	    }
+	  else
+	    {
+	      if (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT)
+		return builtin_type_long_long;
+	      else
+		return builtin_type_long;
+	    }
+	}
+    }
+}
 
 /* Integer exponentiation: V1**V2, where both arguments are
    integers.  Requires V1 != 0 if V2 < 0.  Returns 1 for 0 ** 0.  */
@@ -870,23 +1154,14 @@ struct value *
 value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 {
   struct value *val;
-  struct type *type1, *type2;
+  struct type *result_type;
 
   arg1 = coerce_ref (arg1);
   arg2 = coerce_ref (arg2);
-  type1 = check_typedef (value_type (arg1));
-  type2 = check_typedef (value_type (arg2));
 
-  if ((TYPE_CODE (type1) != TYPE_CODE_FLT
-       && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT && !is_integral_type (type1))
-      ||
-      (TYPE_CODE (type2) != TYPE_CODE_FLT
-       && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT && !is_integral_type (type2)))
-    error (_("Argument to arithmetic operation not a number or boolean."));
+  result_type = binop_result_type (op, value_type (arg1), value_type (arg2));
 
-  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
-      ||
-      TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+  if (TYPE_CODE (result_type) == TYPE_CODE_DECFLOAT)
     {
       struct type *v_type;
       int len_v1, len_v2, len_v;
@@ -909,23 +1184,9 @@ value_binop (struct value *arg1, struct 
 	  error (_("Operation not valid for decimal floating point number."));
 	}
 
-      if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
-	/* If arg1 is not a decimal float, the type of the result is the type
-	   of the decimal float argument, arg2.  */
-	v_type = type2;
-      else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
-	/* Same logic, for the case where arg2 is not a decimal float.  */
-	v_type = type1;
-      else
-	/* len_v is equal either to len_v1 or to len_v2.  the type of the
-	   result is the type of the argument with the same length as v.  */
-	v_type = (len_v == len_v1)? type1 : type2;
-
-      val = value_from_decfloat (v_type, v);
+      val = value_from_decfloat (result_type, v);
     }
-  else if (TYPE_CODE (type1) == TYPE_CODE_FLT
-	   ||
-	   TYPE_CODE (type2) == TYPE_CODE_FLT)
+  else if (TYPE_CODE (result_type) == TYPE_CODE_FLT)
     {
       /* FIXME-if-picky-about-floating-accuracy: Should be doing this
          in target format.  real.c in GCC probably has the necessary
@@ -970,20 +1231,10 @@ value_binop (struct value *arg1, struct 
 	  error (_("Integer-only operation on floating point number."));
 	}
 
-      /* If either arg was long double, make sure that value is also long
-         double.  */
-
-      if (TYPE_LENGTH (type1) * 8 > gdbarch_double_bit (current_gdbarch)
-	  || TYPE_LENGTH (type2) * 8 > gdbarch_double_bit (current_gdbarch))
-	val = allocate_value (builtin_type_long_double);
-      else
-	val = allocate_value (builtin_type_double);
-
+      val = allocate_value (result_type);
       store_typed_floating (value_contents_raw (val), value_type (val), v);
     }
-  else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
-	   &&
-	   TYPE_CODE (type2) == TYPE_CODE_BOOL)
+  else if (TYPE_CODE (result_type) == TYPE_CODE_BOOL)
     {
       LONGEST v1, v2, v = 0;
       v1 = value_as_long (arg1);
@@ -1015,74 +1266,33 @@ value_binop (struct value *arg1, struct 
 	  error (_("Invalid operation on booleans."));
 	}
 
-      val = allocate_value (type1);
+      val = allocate_value (result_type);
       store_signed_integer (value_contents_raw (val),
-			    TYPE_LENGTH (type1),
+			    TYPE_LENGTH (result_type),
 			    v);
     }
   else
     /* Integral operations here.  */
-    /* FIXME:  Also mixed integral/booleans, with result an integer. */
-    /* FIXME: This implements ANSI C rules (also correct for C++).
-       What about FORTRAN and (the deleted) chill ?  */
     {
-      unsigned int promoted_len1 = TYPE_LENGTH (type1);
-      unsigned int promoted_len2 = TYPE_LENGTH (type2);
-      int is_unsigned1 = TYPE_UNSIGNED (type1);
-      int is_unsigned2 = TYPE_UNSIGNED (type2);
-      unsigned int result_len;
-      int unsigned_operation;
-
-      /* Determine type length and signedness after promotion for
-         both operands.  */
-      if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
-	{
-	  is_unsigned1 = 0;
-	  promoted_len1 = TYPE_LENGTH (builtin_type_int);
-	}
-      if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
-	{
-	  is_unsigned2 = 0;
-	  promoted_len2 = TYPE_LENGTH (builtin_type_int);
-	}
-
-      /* Determine type length of the result, and if the operation should
-         be done unsigned.  For exponentiation and shift operators,
-         use the length and type of the left operand.  Otherwise,
-         use the signedness of the operand with the greater length.
-         If both operands are of equal length, use unsigned operation
-         if one of the operands is unsigned.  */
-      if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP)
-	{
-	  /* In case of the shift operators and exponentiation the type of
-	     the result only depends on the type of the left operand.  */
-	  unsigned_operation = is_unsigned1;
-	  result_len = promoted_len1;
-	}
-      else if (promoted_len1 > promoted_len2)
-	{
-	  unsigned_operation = is_unsigned1;
-	  result_len = promoted_len1;
-	}
-      else if (promoted_len2 > promoted_len1)
-	{
-	  unsigned_operation = is_unsigned2;
-	  result_len = promoted_len2;
-	}
-      else
-	{
-	  unsigned_operation = is_unsigned1 || is_unsigned2;
-	  result_len = promoted_len1;
-	}
+      int unsigned_operation = TYPE_UNSIGNED (result_type);
 
       if (unsigned_operation)
 	{
+	  unsigned int len1, len2, result_len;
 	  LONGEST v2_signed = value_as_long (arg2);
 	  ULONGEST v1, v2, v = 0;
 	  v1 = (ULONGEST) value_as_long (arg1);
 	  v2 = (ULONGEST) v2_signed;
 
-	  /* Truncate values to the type length of the result.  */
+	  /* Truncate values to the type length of the result.
+	     Things are mildly trick because binop_result_type may
+	     return a long which on amd64 is 8 bytes, and that's a problem if
+	     ARG1, ARG2 are both <= 4 bytes.  We need to truncate the values
+	     at 4 bytes not 8.  So fetch the lengths of the original types
+	     and truncate at the larger of the two.  */
+	  len1 = TYPE_LENGTH (value_type (arg1));
+	  len2 = TYPE_LENGTH (value_type (arg1));
+	  result_len = len1 > len2 ? len1 : len2;
 	  if (result_len < sizeof (ULONGEST))
 	    {
 	      v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
@@ -1186,19 +1396,7 @@ value_binop (struct value *arg1, struct 
 	      error (_("Invalid binary operation on numbers."));
 	    }
 
-	  /* This is a kludge to get around the fact that we don't
-	     know how to determine the result type from the types of
-	     the operands.  (I'm not really sure how much we feel the
-	     need to duplicate the exact rules of the current
-	     language.  They can get really hairy.  But not to do so
-	     makes it hard to document just what we *do* do).  */
-
-	  /* Can't just call init_type because we wouldn't know what
-	     name to give the type.  */
-	  val = allocate_value
-	    (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT
-	     ? builtin_type_unsigned_long_long
-	     : builtin_type_unsigned_long);
+	  val = allocate_value (result_type);
 	  store_unsigned_integer (value_contents_raw (val),
 				  TYPE_LENGTH (value_type (val)),
 				  v);
@@ -1309,19 +1507,7 @@ value_binop (struct value *arg1, struct 
 	      error (_("Invalid binary operation on numbers."));
 	    }
 
-	  /* This is a kludge to get around the fact that we don't
-	     know how to determine the result type from the types of
-	     the operands.  (I'm not really sure how much we feel the
-	     need to duplicate the exact rules of the current
-	     language.  They can get really hairy.  But not to do so
-	     makes it hard to document just what we *do* do).  */
-
-	  /* Can't just call init_type because we wouldn't know what
-	     name to give the type.  */
-	  val = allocate_value
-	    (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT
-	     ? builtin_type_long_long
-	     : builtin_type_long);
+	  val = allocate_value (result_type);
 	  store_signed_integer (value_contents_raw (val),
 				TYPE_LENGTH (value_type (val)),
 				v);
@@ -1533,23 +1719,19 @@ struct value *
 value_pos (struct value *arg1)
 {
   struct type *type;
+  struct type *result_type;
 
   arg1 = coerce_ref (arg1);
-
   type = check_typedef (value_type (arg1));
+  result_type = unop_result_type (UNOP_PLUS, value_type (arg1));
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    return value_from_double (type, value_as_double (arg1));
+    return value_from_double (result_type, value_as_double (arg1));
   else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
-    return value_from_decfloat (type, value_contents (arg1));
+    return value_from_decfloat (result_type, value_contents (arg1));
   else if (is_integral_type (type))
     {
-      /* Perform integral promotion for ANSI C/C++.  FIXME: What about
-         FORTRAN and (the deleted) chill ?  */
-      if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
-	type = builtin_type_int;
-
-      return value_from_longest (type, value_as_long (arg1));
+      return value_from_longest (result_type, value_as_long (arg1));
     }
   else
     {
@@ -1562,11 +1744,11 @@ struct value *
 value_neg (struct value *arg1)
 {
   struct type *type;
-  struct type *result_type = value_type (arg1);
+  struct type *result_type;
 
   arg1 = coerce_ref (arg1);
-
   type = check_typedef (value_type (arg1));
+  result_type = unop_result_type (UNOP_NEG, value_type (arg1));
 
   if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
     {
@@ -1584,16 +1766,10 @@ value_neg (struct value *arg1)
       memcpy (value_contents_raw (val), decbytes, len);
       return val;
     }
-
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT)
     return value_from_double (result_type, -value_as_double (arg1));
   else if (is_integral_type (type))
     {
-      /* Perform integral promotion for ANSI C/C++.  FIXME: What about
-         FORTRAN and (the deleted) chill ?  */
-      if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
-	result_type = builtin_type_int;
-
       return value_from_longest (result_type, -value_as_long (arg1));
     }
   else
@@ -1607,20 +1783,15 @@ struct value *
 value_complement (struct value *arg1)
 {
   struct type *type;
-  struct type *result_type = value_type (arg1);
+  struct type *result_type;
 
   arg1 = coerce_ref (arg1);
-
   type = check_typedef (value_type (arg1));
+  result_type = unop_result_type (UNOP_COMPLEMENT, value_type (arg1));
 
   if (!is_integral_type (type))
     error (_("Argument to complement operation not an integer or boolean."));
 
-  /* Perform integral promotion for ANSI C/C++.
-     FIXME: What about FORTRAN ?  */
-  if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
-    result_type = builtin_type_int;
-
   return value_from_longest (result_type, ~value_as_long (arg1));
 }
 
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.182
diff -u -p -r1.182 valops.c
--- valops.c	18 Jan 2008 17:07:40 -0000	1.182
+++ valops.c	30 Jan 2008 17:11:58 -0000
@@ -471,6 +471,41 @@ value_zero (struct type *type, enum lval
   return val;
 }
 
+/* Create a value of numeric type TYPE that is one, and return it.  */
+
+struct value *
+value_one (struct type *type, enum lval_type lv)
+{
+  struct type *type1 = check_typedef (type);
+  struct value *val;
+
+  if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
+    {
+      struct value *int_one = value_from_longest (builtin_type_int, 1);
+      struct value *val;
+      gdb_byte v[16];
+
+      decimal_from_integral (int_one, v, TYPE_LENGTH (builtin_type_int));
+      val = value_from_decfloat (type, v);
+      value_free (int_one);
+    }
+  else if (TYPE_CODE (type1) == TYPE_CODE_FLT)
+    {
+      val = value_from_double (type, (DOUBLEST) 1);
+    }
+  else if (is_integral_type (type1))
+    {
+      val = value_from_longest (type, (LONGEST) 1);
+    }
+  else
+    {
+      error (_("Not a numeric type."));
+    }
+
+  VALUE_LVAL (val) = lv;
+  return val;
+}
+
 /* Return a value with type TYPE located at ADDR.
 
    Call value_at only if the data needs to be fetched immediately;
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.107
diff -u -p -r1.107 value.h
--- value.h	18 Jan 2008 17:07:40 -0000	1.107
+++ value.h	30 Jan 2008 17:11:58 -0000
@@ -392,6 +392,8 @@ extern struct value *value_cast (struct 
 
 extern struct value *value_zero (struct type *type, enum lval_type lv);
 
+extern struct value *value_one (struct type *type, enum lval_type lv);
+
 extern struct value *value_repeat (struct value *arg1, int count);
 
 extern struct value *value_subscript (struct value *array, struct value *idx);
Index: testsuite/gdb.base/whatis-exp.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/whatis-exp.exp,v
retrieving revision 1.7
diff -u -p -r1.7 whatis-exp.exp
--- testsuite/gdb.base/whatis-exp.exp	1 Jan 2008 22:53:19 -0000	1.7
+++ testsuite/gdb.base/whatis-exp.exp	30 Jan 2008 17:12:00 -0000
@@ -112,7 +112,7 @@ gdb_expect {
 
 send_gdb "whatis x+y\n"
 gdb_expect {
-    -re ".*type = long.*$gdb_prompt $" {
+    -re ".*type = int.*$gdb_prompt $" {
         pass "whatis value of x+y"
       }
     -re ".*$gdb_prompt $" { fail "whatis value of x+y" }
@@ -121,7 +121,7 @@ gdb_expect {
 
 send_gdb "whatis x-y\n"
 gdb_expect {
-    -re ".*type = long.*$gdb_prompt $" {
+    -re ".*type = int.*$gdb_prompt $" {
         pass "whatis value of x-y"
       }
     -re ".*$gdb_prompt $" { fail "whatis value of x-y" }
@@ -130,7 +130,7 @@ gdb_expect {
 
 send_gdb "whatis x*y\n"
 gdb_expect {
-    -re ".*type = long.*$gdb_prompt $" {
+    -re ".*type = int.*$gdb_prompt $" {
         pass "whatis value of x*y"
       }
     -re ".*$gdb_prompt $" { fail "whatis value of x*y" }


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