aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul N. Hilfinger <hilfinger@adacore.com>2008-01-30 07:28:16 +0000
committerPaul N. Hilfinger <hilfinger@adacore.com>2008-01-30 07:28:16 +0000
commitd118ef8764180584e6b42b38d8c68c18bf8c83c4 (patch)
tree7b0451b86d7f4eb95586ba07e83e7629ee40c041
parentd56d46f5c7560a45f3a1c6101893ca84969c98a9 (diff)
downloadgdb-d118ef8764180584e6b42b38d8c68c18bf8c83c4.zip
gdb-d118ef8764180584e6b42b38d8c68c18bf8c83c4.tar.gz
gdb-d118ef8764180584e6b42b38d8c68c18bf8c83c4.tar.bz2
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 Paul N. Hilfinger <hilfinger@adacore.com> * gdb.ada/exprs: New test program. * gdb.ada/exprs.exp: New testcase.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.ada/exprs.exp50
-rw-r--r--gdb/testsuite/gdb.ada/exprs/p.adb41
-rw-r--r--gdb/valarith.c92
5 files changed, 185 insertions, 14 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1eecd4b..67fbd01 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6bc429a..f198e03 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
index 0000000..0283bb1
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/exprs.exp
@@ -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
index 0000000..b342c98
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/exprs/p.adb
@@ -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;
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 2fa435d..e69aaa6 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -743,6 +743,66 @@ value_concat (struct value *arg1, struct value *arg2)
}
+/* 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: