2008-01-30 Paul N. Hilfinger <hilfinger@adacore.com>
authorPaul N. Hilfinger <hilfinger@adacore.com>
Wed, 30 Jan 2008 07:28:16 +0000 (07:28 +0000)
committerPaul N. Hilfinger <hilfinger@adacore.com>
Wed, 30 Jan 2008 07:28:16 +0000 (07:28 +0000)
* valarith.c (value_binop): Add floating-point BINOP_MIN and
BINOP_MAX cases.
For BINOP_EXP, use length and signedness of left operand only for
result, as for shifts.
For integral operands to BINOP_EXP, use new integer_pow and
uinteger_pow functions so as to get full range of results.
(integer_pow): New function.
(uinteger_pow): New function.

2008-01-30  Paul N. Hilfinger  <hilfinger@adacore.com>

* gdb.ada/exprs: New test program.
* gdb.ada/exprs.exp: New testcase.

gdb/ChangeLog
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/exprs.exp [new file with mode: 0644]
gdb/testsuite/gdb.ada/exprs/p.adb [new file with mode: 0644]
gdb/valarith.c

index 1eecd4bdc8ec9a62300955639a230340ea800e9e..67fbd01d3aeaa10f8374a0dfa1064035386a58c9 100644 (file)
@@ -1,3 +1,14 @@
+2008-01-30  Paul N. Hilfinger  <hilfinger@adacore.com>
+
+       * valarith.c (value_binop): Add floating-point BINOP_MIN and
+       BINOP_MAX cases.
+       For BINOP_EXP, use length and signedness of left operand only for
+       result, as for shifts.
+       For integral operands to BINOP_EXP, use new integer_pow and
+       uinteger_pow functions so as to get full range of results.
+       (integer_pow): New function.
+       (uinteger_pow): New function.
+
 2008-01-30  Vladimir Prus  <vladimir@codesourcery.com>
 
        Use vector for varobj_list_children interface.
index 6bc429a62a2a8f322dad9100dc8e1535c87d8e3c..f198e03e7b9c4fd0f53121468df7635c2737e4df 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-30  Paul N. Hilfinger  <hilfinger@adacore.com>
+
+       * gdb.ada/exprs: New test program.
+       * gdb.ada/exprs.exp: New testcase.
+
 2008-01-30  Thiago Jung Bauermann  <bauerman@br.ibm.com>
 
        * dfp-test.c (DELTA, DELTA_B): New definitions.
diff --git a/gdb/testsuite/gdb.ada/exprs.exp b/gdb/testsuite/gdb.ada/exprs.exp
new file mode 100644 (file)
index 0000000..0283bb1
--- /dev/null
@@ -0,0 +1,50 @@
+# Copyright 2005, 2007 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+load_lib "ada.exp"
+
+set testdir "exprs"
+set testfile "${testdir}/p"
+set srcfile ${srcdir}/${subdir}/${testfile}.adb
+set binfile ${objdir}/${subdir}/${testfile}
+
+file mkdir ${objdir}/${subdir}/${testdir}
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+  return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set bp_location [gdb_get_line_number "START" ${testdir}/p.adb]
+runto "p.adb:$bp_location"
+
+gdb_test "print X ** Y = Z" \
+         "true" \
+         "Long_Long_Integer ** Y"
+
+gdb_test "print long_float'min (long_float (X), 8.0)" \
+         "7.0" \
+         "long_float'min"
+
+gdb_test "print long_float'max (long_float (X), 8.0)" \
+         "8.0" \
+         "long_float'max"
diff --git a/gdb/testsuite/gdb.ada/exprs/p.adb b/gdb/testsuite/gdb.ada/exprs/p.adb
new file mode 100644 (file)
index 0000000..b342c98
--- /dev/null
@@ -0,0 +1,41 @@
+--  Copyright 2008 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+--  Test Ada additions to core GDB evaluation.
+
+with System;
+with Text_IO; use Text_IO;
+
+procedure P is
+   type Int is range System.Min_Int .. System.Max_Int;
+
+   X, Z : Int;
+   Y : Integer;
+
+begin
+   X := 0;
+   -- Set X to 7 by disguised means lest a future optimizer interfere.
+   for I in 1 .. 7 loop
+      X := X + 1;
+   end loop;
+   Z := 1;
+   Y := 0;
+   while Z < Int'Last / X loop
+      Z := Z * X;
+      Y := Y + 1;
+   end loop;
+
+   Put_Line (Int'Image (X ** Y));  -- START
+end P;
index 2fa435d446de847a388a09517dc76c58d09ee730..e69aaa67567d0925c2b50778746a94e65a2a1690 100644 (file)
@@ -743,6 +743,66 @@ value_concat (struct value *arg1, struct value *arg2)
 }
 \f
 
+/* Integer exponentiation: V1**V2, where both arguments are
+   integers.  Requires V1 != 0 if V2 < 0.  Returns 1 for 0 ** 0.  */
+static LONGEST
+integer_pow (LONGEST v1, LONGEST v2)
+{
+  if (v2 < 0)
+    {
+      if (v1 == 0)
+       error (_("Attempt to raise 0 to negative power."));
+      else
+       return 0;
+    }
+  else 
+    {
+      /* The Russian Peasant's Algorithm */
+      LONGEST v;
+      
+      v = 1;
+      for (;;)
+       {
+         if (v2 & 1L) 
+           v *= v1;
+         v2 >>= 1;
+         if (v2 == 0)
+           return v;
+         v1 *= v1;
+       }
+    }
+}
+
+/* Integer exponentiation: V1**V2, where both arguments are
+   integers.  Requires V1 != 0 if V2 < 0.  Returns 1 for 0 ** 0.  */
+static ULONGEST
+uinteger_pow (ULONGEST v1, LONGEST v2)
+{
+  if (v2 < 0)
+    {
+      if (v1 == 0)
+       error (_("Attempt to raise 0 to negative power."));
+      else
+       return 0;
+    }
+  else 
+    {
+      /* The Russian Peasant's Algorithm */
+      ULONGEST v;
+      
+      v = 1;
+      for (;;)
+       {
+         if (v2 & 1L) 
+           v *= v1;
+         v2 >>= 1;
+         if (v2 == 0)
+           return v;
+         v1 *= v1;
+       }
+    }
+}
+
 /* Obtain decimal value of arguments for binary operation, converting from
    other types if one of them is not decimal floating point.  */
 static void
@@ -898,6 +958,14 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
            error (_("Cannot perform exponentiation: %s"), safe_strerror (errno));
          break;
 
+       case BINOP_MIN:
+         v = v1 < v2 ? v1 : v2;
+         break;
+             
+       case BINOP_MAX:
+         v = v1 > v2 ? v1 : v2;
+         break;
+
        default:
          error (_("Integer-only operation on floating point number."));
        }
@@ -979,14 +1047,15 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
        }
 
       /* Determine type length of the result, and if the operation should
-         be done unsigned.
-         Use the signedness of the operand with the greater length.
+         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)
+      if (op == BINOP_RSH || op == BINOP_LSH || op == BINOP_EXP)
        {
-         /* In case of the shift operators the type of the result only
-            depends on the type of the left operand.  */
+         /* 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;
        }
@@ -1008,9 +1077,10 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 
       if (unsigned_operation)
        {
+         LONGEST v2_signed = value_as_long (arg2);
          ULONGEST v1, v2, v = 0;
          v1 = (ULONGEST) value_as_long (arg1);
-         v2 = (ULONGEST) value_as_long (arg2);
+         v2 = (ULONGEST) v2_signed;
 
          /* Truncate values to the type length of the result.  */
          if (result_len < sizeof (ULONGEST))
@@ -1042,10 +1112,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
              break;
 
            case BINOP_EXP:
-             errno = 0;
-             v = pow (v1, v2);
-             if (errno)
-               error (_("Cannot perform exponentiation: %s"), safe_strerror (errno));
+              v = uinteger_pow (v1, v2_signed);
              break;
 
            case BINOP_REM:
@@ -1165,10 +1232,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
               break;
 
            case BINOP_EXP:
-             errno = 0;
-             v = pow (v1, v2);
-             if (errno)
-               error (_("Cannot perform exponentiation: %s"), safe_strerror (errno));
+              v = integer_pow (v1, v2);
              break;
 
            case BINOP_REM: