Menu ▾ ▴

#1293 DIVIDE ... REMAINDER stores the remainder when the quotient has a size error under ON SIZE ERROR

unclassified
open
nobody
None
5 - default
2026-11-04
2026-11-04
No

When DIVIDE ... GIVING q REMAINDER r has an ON SIZE ERROR phrase and the quotient does not fit q, cobc leaves q unchanged and runs the phrase, but it still stores a remainder into r.

To reproduce

divrem.cob (attached):

       IDENTIFICATION DIVISION.
       PROGRAM-ID. DIVREM.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 Q PIC 99 VALUE 11.
       01 R PIC 99 VALUE 5.
       PROCEDURE DIVISION.
           DIVIDE 7 INTO 1000 GIVING Q REMAINDER R
               ON SIZE ERROR DISPLAY "SIZE ERROR Q=" Q " R=" R
               NOT ON SIZE ERROR DISPLAY "NO SIZE ERROR Q=" Q " R=" R
           END-DIVIDE
           STOP RUN.
cobc -std=cobol2014 -x divrem.cob && ./divrem

What happens

3.2.0 and 3.3-dev r5751 both print (run exit 0)

SIZE ERROR Q=11 R=06

1000 / 7 is 142.857..., so Q keeps 11, but R changes from 05 to 06, which is 1000 - 142 * 7. divrem2.cob, attached, shows the same with format 5 (DIVIDE 1000 BY 7 GIVING Q REMAINDER R, R=006), and round.cob, attached, when ROUNDED causes the size error (DIVIDE 2 INTO 199 GIVING Q ROUNDED REMAINDER R, R=01).

What should happen

divrem should print SIZE ERROR Q=11 R=05, divrem2 R=005 and round R=05. 142 (and in round the rounded 100) does not fit Q (PIC 99), so Q is not changed (ISO/IEC 1989:2023 14.7.5 rule 2), and 14.9.12.4 rule 6 c) develops the subsidiary quotient and stores the remainder only "If the size error condition is not raised". The same in 2002 and in the 2014 FCD.

Why it happens

In libcob/numeric.c, cob_div_quotient ignores the size error that cob_decimal_get_field reports for the quotient and always computes the remainder, from the quotient truncated to q's scale but not to q's number of digits.

Proposed fix

The attached n10-divide-remainder-size-error.patch (against 3.3-dev r5751) changes code only in libcob/numeric.c: if the quotient store reports a size error and opt has COB_STORE_KEEP_ON_OVERFLOW, cob_div_quotient sets a new flag cob_d_remainder_skip, and cob_div_remainder then returns without storing. Without any SIZE ERROR phrase nothing changes (Q=42 R=06). With only NOT ON SIZE ERROR, cobc already keeps a DISPLAY or BINARY Q unchanged, and R is now kept unchanged with it. The patch adds test 621, "DIVIDE REMAINDER with SIZE ERROR on the quotient", to run_fundamental.at, with a libcob/ChangeLog entry. make check: 1373 expected, 9 skipped, 0 failed (1372 unpatched); the new test fails without the patch.

  • #1282: its patch changes when cobc sets COB_STORE_KEEP_ON_OVERFLOW, the flag this patch tests; this patch applies on top of it with a line offset in run_fundamental.at.
  • #1285: another receiving item changed although the SIZE ERROR phrase runs (0 ** 0); this patch also applies on top of its patch.
  • #1254: the static work decimals in numeric.c are not thread-safe; the new flag would move with cob_d_remainder.

Details

GnuCOBOL 3.2.0 (Ubuntu gnucobol3 3.2-4build1) and 3.3-dev r5751 (CI snapshot 3.3-dev.138 of 2026-10-29), x86_64 Linux, both run 2026-11-04.

4 Attachments

Discussion


Log in to post a comment.