https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127840

            Bug ID: 127840
           Summary: [DebugInfo] wrong GDB values for narrow signed
                    arithmetic in optimized DWARF expressions
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: MrEven132 at outlook dot com
  Target Milestone: ---

With GCC 17.0.0 20261003 (experimental) and GDB 17.2 on AArch64, several
independent signed-arithmetic examples in one source file have incorrect GDB
values at -O1.  The same variables and breakpoints give the expected values at
-O0.  This report groups division, remainder, arithmetic right shift, abs, and
_BitInt(7) arithmetic because their optimized DWARF expressions appear to lose
the signed width of operands.

Test case (case.c):

    volatile int sink32;
    volatile int sink32_mod;
    volatile int sink32_shift_abs;
    volatile int sink_bitint;

    __attribute__((noinline)) int signed_div32_live_operands (int a, int b)
    {
      int x = a / b;
      sink32 += a + b;
      return 0;
    }

    __attribute__((noinline)) int signed_mod32_live_operands (int a, int b)
    {
      int x = a % b;
      sink32_mod += a + b;
      return 0;
    }

    __attribute__((noinline)) int signed_shift_abs32_live_operand (int a, int
s)
    {
      int x = a >> s;
      int y = __builtin_abs (a);
      sink32_shift_abs += a + s;
      return 0;
    }

    __attribute__((noinline)) int test_bitint_signed (_BitInt(7) a, _BitInt(7)
b)
    {
      _BitInt(7) quotient = a / b;
      _BitInt(7) remainder = a % b;
      sink_bitint += a + b;
      return quotient + remainder;
    }

    int main (void)
    {
      signed_div32_live_operands (-7, 2);
      signed_mod32_live_operands (-7, 2);
      signed_shift_abs32_live_operand (-7, 1);
      return test_bitint_signed (-55, 3);
    }

Build on AArch64:

    gcc -O0 -g case.c -o case-O0
    gcc -O1 -g case.c -o case-O1

In GDB, load one executable at a time, set breakpoints at case.c:9, case.c:16,
case.c:24, and case.c:32, then run.  The program reaches these breakpoints in
that order.  Print x at the first two; print x and y at the third; print
quotient and remainder at the fourth.  Repeat with each executable, using a
fresh GDB session.

                           Expected   GDB -O0   GDB -O1
    int division x             -3         -3    2147483644
    int remainder x            -1         -1             1
    right shift x              -4         -4    2147483644
    abs y                       7          7            -7
    _BitInt(7) quotient       -18        -18           -61
    _BitInt(7) remainder       -1         -1             0

For example, at case.c:9 in the optimized build, a = -7 and b = 2, but GDB
prints x = 2147483644 instead of -3.  At the breakpoint, x0 is 0xfffffff9 and
x1 is 0x2.  The DWARF location for x is:

    DW_OP_breg0 W0+0, DW_OP_breg1 W1+0, DW_OP_div, DW_OP_stack_value

The expression appears to divide 0x00000000fffffff9 by 2 at the generic DWARF
stack width, yielding 2147483644 instead of evaluating signed 32-bit -7 / 2. 
The other optimized values likewise use sign-sensitive DWARF arithmetic without
restoring the source operands' signed width.  The discrepancy is in the
generated debug information; the test case's source arithmetic has the expected
values.

Reply via email to