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

            Bug ID: 125577
           Summary: Floating-point (COMP-1/COMP-2) subtraction in
                    COMPUTE/SUBTRACT returns a stale temporary instead of
                    the difference
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: cobol
          Assignee: unassigned at gcc dot gnu.org
          Reporter: peeterjoot at protonmail dot com
  Target Milestone: ---

Created attachment 64610
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64610&action=edit
reproducer for subtraction bug

- **Host/Target:** aarch64-linux-gnu
- **Compiler:** `gcobol (Ubuntu 15.2.0-16ubuntu1) 15.2.0`

## Description

Subtraction whose result is `USAGE COMP-2` (FLOAT-LONG) or `COMP-1`
(FLOAT-SHORT)
does not compute the difference. The destination instead receives a stale
value — whatever happened to be in the result temporary, or 0 when nothing
preceded it.

This affects:
- the binary `-` operator in `COMPUTE`,
- the unary minus `-(expr)`, and
- the `SUBTRACT` verb.

Addition, multiplication and division on the same operands are correct, and
subtraction on packed-decimal (`PIC S9(n)V9(m)`) and binary-integer (`COMP-5`)
operands is correct — only binary floating point is affected.

## Steps to reproduce

`subbug.cob` (fixed form):

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SUBBUG.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 A COMP-2 VALUE 9.
       01 B COMP-2 VALUE 1.
       01 R COMP-2.
       PROCEDURE DIVISION.
           COMPUTE R = A - B
           DISPLAY 'COMPUTE  A - B      = ' R '   expected 8'
           SUBTRACT B FROM A GIVING R
           DISPLAY 'SUBTRACT B FROM A   = ' R '   expected 8'
           COMPUTE R = A + (B * -1)
           DISPLAY 'COMPUTE  A + (B*-1) = ' R '   expected 8'
           GOBACK.
```

```
$ gcobol -O0 -main -o subbug subbug.cob && ./subbug
COMPUTE  A - B      = 0   expected 8
SUBTRACT B FROM A   = 0   expected 8
COMPUTE  A + (B*-1) = 8   expected 8
```

## Expected vs actual

- **Expected:** all three print 8.
- **Actual:** the two subtractions print 0; the algebraically-equivalent
  `A + (B * -1)` is correct.

## The "stale temporary" nature

If a *different* subtraction precedes it, the broken one returns that earlier
value rather than 0. With `COMPUTE R = 100 - 50` (→ 50) executed first, a
following `COMPUTE R = A - B` (A=9, B=1) prints **50**, not 8. So the result of
the subtraction is never stored; the destination reads an uninitialized /
previous temporary.

## Scope

Single program, `COMPUTE x = a - b` with variable operands a=9, b=1:

| result type                | result        |
|----------------------------|---------------|
| `COMP-2` (FLOAT-LONG)      | **wrong (0)** |
| `COMP-1` (FLOAT-SHORT)     | **wrong (0)** |
| `PIC S9(5)V9(2)` (packed)  | correct (8)   |
| `PIC S9(9) COMP-5` (int)   | correct (8)   |

Reproduces at `-O0` through `-O3`.

## Workaround

Express subtraction as addition of a negated product:
- `a - b`   ->  `a + (b * -1)`
- `-(x)`    ->  `(x) * -1`

Reply via email to