From 7005080802d695d112530a7c24c9d3d44ee109a3 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 1 Mar 2023 15:13:39 -0700 Subject: [PATCH] Fix 128-bit integer bug in Ada While working on 128-bit integer support, I found one spot in Ada that needed a fix as well. --- gdb/ada-lang.c | 27 ++++-------------- gdb/testsuite/gdb.ada/verylong.exp | 37 +++++++++++++++++++++++++ gdb/testsuite/gdb.ada/verylong/prog.adb | 20 +++++++++++++ 3 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 gdb/testsuite/gdb.ada/verylong.exp create mode 100644 gdb/testsuite/gdb.ada/verylong/prog.adb diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 067816c2708..5301c72d514 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -62,14 +62,6 @@ #include "charset.h" #include "ax-gdb.h" -/* Define whether or not the C operator '/' truncates towards zero for - differently signed operands (truncation direction is undefined in C). - Copied from valarith.c. */ - -#ifndef TRUNCATION_TOWARDS_ZERO -#define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) -#endif - static struct type *desc_base_type (struct type *); static struct type *desc_bounds_type (struct type *); @@ -9356,9 +9348,7 @@ coerce_for_assign (struct type *type, struct value *val) static struct value * ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) { - struct value *val; struct type *type1, *type2; - LONGEST v, v1, v2; arg1 = coerce_ref (arg1); arg2 = coerce_ref (arg2); @@ -9379,8 +9369,8 @@ ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) return value_binop (arg1, arg2, op); } - v2 = value_as_long (arg2); - if (v2 == 0) + gdb_mpz v2 = value_as_mpz (arg2); + if (v2.sgn () == 0) { const char *name; if (op == BINOP_MOD) @@ -9399,13 +9389,12 @@ ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) if (type1->is_unsigned () || op == BINOP_MOD) return value_binop (arg1, arg2, op); - v1 = value_as_long (arg1); + gdb_mpz v1 = value_as_mpz (arg1); + gdb_mpz v; switch (op) { case BINOP_DIV: v = v1 / v2; - if (!TRUNCATION_TOWARDS_ZERO && v1 * (v1 % v2) < 0) - v += v > 0 ? -1 : 1; break; case BINOP_REM: v = v1 % v2; @@ -9414,14 +9403,10 @@ ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) break; default: /* Should not reach this point. */ - v = 0; + gdb_assert_not_reached ("invalid operator"); } - val = value::allocate (type1); - store_unsigned_integer (val->contents_raw ().data (), - val->type ()->length (), - type_byte_order (type1), v); - return val; + return value_from_mpz (type1, v); } static int diff --git a/gdb/testsuite/gdb.ada/verylong.exp b/gdb/testsuite/gdb.ada/verylong.exp new file mode 100644 index 00000000000..93df785862b --- /dev/null +++ b/gdb/testsuite/gdb.ada/verylong.exp @@ -0,0 +1,37 @@ +# Copyright 2023 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 . + +load_lib "ada.exp" + +require allow_ada_tests + +standard_ada_testfile prog + +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} { + return -1 +} + +clean_restart ${testfile} + +set bp_location [gdb_get_line_number "START" ${testdir}/prog.adb] +runto "prog.adb:$bp_location" + +gdb_test "print x" " = 170141183460469231731687303715884105727" +gdb_test "print x / 2" " = 85070591730234615865843651857942052863" +gdb_test "print (x / 4) * 2" " = 85070591730234615865843651857942052862" +gdb_test "print x - x" " = 0" +gdb_test "print x - 99 + 1" " = 170141183460469231731687303715884105629" +gdb_test "print -x" " = -170141183460469231731687303715884105727" +gdb_test "print +x" " = 170141183460469231731687303715884105727" diff --git a/gdb/testsuite/gdb.ada/verylong/prog.adb b/gdb/testsuite/gdb.ada/verylong/prog.adb new file mode 100644 index 00000000000..766419d0a4f --- /dev/null +++ b/gdb/testsuite/gdb.ada/verylong/prog.adb @@ -0,0 +1,20 @@ +-- Copyright 2023 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 . + +procedure Main is + X : Long_Long_Long_Integer := Long_Long_Long_Integer'Last; +begin + null; -- START +end Main; -- 2.30.2