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

            Bug ID: 126002
           Summary: parenthesized sign condition fails to parse
           Product: gcc
           Version: 17.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 64865
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64865&action=edit
sign conditions, two accepted examples, and one rejected.

## Summary

`gcobol` rejects a **sign condition** (`operand IS [NOT] {POSITIVE | NEGATIVE |
ZERO}`) when it is enclosed in parentheses.

## Environment

```
gcobol (GCC) 17.0.0 20260604 (experimental), target aarch64-linux-gnu
```

## Reproducer

`paren-sign-condition.cob` (this directory). Three conforming `IF`s; gcobol
accepts #1 and #2 but rejects #3:

```cobol
       IF WS-N IS ZERO          *> #1 sign, no parens   -- ACCEPTED
       IF (WS-N = 0)            *> #2 relation, parens  -- ACCEPTED
       IF (WS-N IS ZERO)        *> #3 sign, parens      -- REJECTED
```

```
$ gcobol -c paren-sign-condition.cob -nomain -o /dev/null
paren-sign-condition.cob:28:24: error: syntax error, unexpected ZERO, expecting
class name or OMITTED
   28 |            IF (WS-N IS ZERO)
      |                        ^~~~~
```

`POSITIVE` and `NEGATIVE` fail the same way. Unparenthesized (#1) parses fine,
so the defect is confined to the parenthesized-condition path. The diagnostic
names exactly the *class name* and *OMITTED* alternatives, which suggests the
sign-condition alternative is unreachable in that state.

It is also triggered indirectly when a logical operator forces parentheses
around a sign condition, e.g. `NOT (WS-N IS ZERO)` or
`PERFORM UNTIL (WS-I = 0 OR TBL(WS-I) IS POSITIVE)`.

In the grammar (`gcc/cobol/parse.y`, trunk `c9ee2c5ab6c`; line numbers
approximate) the pieces are all present, so the construct is grammatically
intended: the sign condition is `simple_cond: expr posneg` (~6610), a
parenthesized condition is `log_term: '(' log_expr ')'` (~6684), and `log_expr`
reaches `simple_cond` (~6694). The two alternatives the diagnostic *does* list
are `expr is CLASS_NAME` (~6580) and `expr is OMITTED` (~6594), the siblings of
the sign production. The likely cause is an LALR conflict between the
parenthesized condition (~6684) and a parenthesized arithmetic operand
`factor: '(' expr ')'` (~6876), resolved so that the sign continuation is lost
while the class/omitted continuations survive.

## Why it is a bug

A sign condition is a *simple condition*, and a simple condition may be
parenthesized freely. From the IBM Enterprise COBOL for z/OS 6.5 Language
Reference (SC27-8713-04):

- "Simple conditions" (p.274) lists the six simple conditions, including the
  **sign** condition.
- "Conditional expressions" (p.274): *"Both simple and complex conditions can
be
  enclosed within any number of paired parentheses; the parentheses do not
  change whether the condition is simple or complex."*
- "Order of evaluation of conditions" (p.292) gives IBM's own
fully-parenthesized
  evaluation form containing a parenthesized sign condition directly:
  `... AND (D IS POSITIVE)`.

So `(WS-N IS ZERO)` should be conforming COBOL, at least for the IBM dialect,
but probably generally. gcobol accepting the unparenthesized
sign form and the parenthesized relation/class forms, while rejecting only the
parenthesized sign form, marks this as a grammar omission rather than a dialect
restriction.

## Workaround

This issue was observed running our COBOL "clang-format" like tool, which was
over parenthesizing -- I've added a GcobolCompat: option to that tool to work
around this.  When that option is used, I attempt to drop parentheses that can
be implied by precedence (standard precedence is `NOT > AND > OR`),
e.g.`NOT (WS-N IS ZERO)` -> `NOT WS-N IS ZERO`.

That workaround is not always possible: when parentheses are required to
override
precedence (a sign condition inside `(a OR b) AND c`), the expression must be
restructured instead.

Reply via email to