Skip to content

COBOL engine: inline PERFORM forms produce phantom callees (TEST, FOREVER, WS-N of WS-N TIMES, 3, END-IF after EXIT PERFORM) #4305

Description

@squid-protocol

Problem

The calls_out rule (cobol.py:875) takes the word after any PERFORM. _calls_out_ignore excludes only varying, until and with. These inline forms name no paragraph, yet each is recorded as a callee:

  • PERFORM TEST BEFORE|AFTER ... (WITH is optional) -> TEST
  • PERFORM FOREVER (GnuCOBOL / Micro Focus) -> FOREVER
  • PERFORM 3 TIMES / PERFORM WS-N TIMES (inline) -> 3 / WS-N
  • EXIT PERFORM [CYCLE] -> the next token (END-IF, CYCLE)

Evidence

Impact

Phantom unresolved callees in the function graph. A data name (WS-N) can collide with a real paragraph name and draw a false edge.

Acceptance criteria

  • test, forever ignored; <literal|identifier> TIMES without a following procedure name ignored; EXIT PERFORM not read as a PERFORM
  • Fixtures for each form, plus PERFORM PARA-X 3 TIMES (out-of-line, still a callee)

Found during: crucible mainframe count audit (2026-10-04)

Reproducer

REPRO2.cbl

       IDENTIFICATION DIVISION.
       PROGRAM-ID. REPRO2.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-I                   PIC 9(4) COMP VALUE 0.
       PROCEDURE DIVISION.
       MAIN-PARA.
           PERFORM WITH TEST AFTER VARYING WS-I FROM 1 BY 1
                   UNTIL WS-I > 2
              DISPLAY WS-I
           END-PERFORM
           PERFORM TEST BEFORE UNTIL WS-I > 9
              ADD 1 TO WS-I
           END-PERFORM
           PERFORM WORK-PARA WITH TEST AFTER UNTIL WS-I > 20
           STOP RUN.
       WORK-PARA.
           ADD 1 TO WS-I.

REPRO3.cbl

       IDENTIFICATION DIVISION.
       PROGRAM-ID. REPRO3.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-I                   PIC 9(4) COMP VALUE 0.
       01  WS-N                   PIC 9(4) COMP VALUE 3.
       PROCEDURE DIVISION.
       MAIN-PARA.
           PERFORM WS-N TIMES
              ADD 1 TO WS-I
           END-PERFORM
           PERFORM 3 TIMES
              ADD 1 TO WS-I
           END-PERFORM
           PERFORM FOREVER
              ADD 1 TO WS-I
              IF WS-I > 50 EXIT PERFORM END-IF
           END-PERFORM
           CALL 'CBLTDLI' USING WS-I
           STOP RUN.

Found by a grep-vs-engine count audit of every mainframe file in language-crucible v1.7.0 (802 of 815 files compared), on main 737cab8 and the #4290 head (now merged as c136f46).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing enginelegacy-modernizationCOBOL refractor, dead-code extraction, and JCL forgingpriority: lowUI tweaks, documentation, and minor optimizations

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions