Menu ▾ ▴

#1299 GLOBAL on a level-1 LOCAL-STORAGE item is refused ("GLOBAL not allowed here")

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

cobc refuses the GLOBAL clause on a level-1 item in the LOCAL-STORAGE SECTION, so a contained program cannot reference that item. ISO allows GLOBAL there, as in the file, working-storage and linkage sections.

To reproduce

glbls.cob (attached, free format):

IDENTIFICATION DIVISION.
PROGRAM-ID. GLBLS.
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 L1 IS GLOBAL PIC 99 VALUE 11.
PROCEDURE DIVISION.
    DISPLAY L1
    CALL "GLBLS-IN"
    DISPLAY L1
    STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. GLBLS-IN.
PROCEDURE DIVISION.
    DISPLAY L1
    ADD 1 TO L1
    GOBACK.
END PROGRAM GLBLS-IN.
END PROGRAM GLBLS.
cobc -x -free -std=cobol2014 -fno-diagnostics-show-caret glbls.cob && ./glbls

What happens

3.2.0 and 3.3-dev r5751 both stop with

glbls.cob:5: error: GLOBAL not allowed here
glbls.cob:14: error: 'L1' is not defined

The same happens without -std and with -std=cobol2002, ibm and mf, and for glbrec.cob, attached, a RECURSIVE program whose contained program displays the item.

What should happen

The program should print 11, 11 and 12. ISO/IEC 1989:2023 13.18.27.3 syntax rule 1 b) allows GLOBAL in "A data description entry whose level-number is 1 that is specified in the file, working-storage, local-storage, or linkage section", and general rule 2 lets a contained program reference a global name without describing it again; the same in 2002 and in the 2014 FCD.

Why it happens

global_clause in cobc/parser.y refuses GLOBAL when current_storage == CB_STORAGE_LOCAL. Dropping that branch alone is not enough: LOCAL-STORAGE is addressed through cob_local_ptr, a local variable of the containing program's C function, so the C compile of the contained program fails with "'cob_local_ptr' undeclared".

Proposed fix

The attached n10-global-local-storage.patch (against 3.3-dev r5751) drops that branch and, in cobc/codegen.c, gives each GLOBAL LOCAL-STORAGE record a static base pointer, and each index-name of its tables a static int, both at file scope, where GLOBAL WORKING-STORAGE storage already is. output_internal_function points each record's pointer into the new LOCAL-STORAGE, saves the previous pointers and index values on entry and restores them on exit, so every activation of a recursive program has its own copy; a USE GLOBAL declarative entered from a contained program keeps the active ones. output_base, output_nonlocal_base_cache and create_field use, declare and cache them, with a new flag in tree.h. A LOCAL-STORAGE with no GLOBAL item generates the same code as before. With the patch glbls prints 11, 11, 12 and glbrec prints 3, 2, 1.

A BASED GLOBAL item is now accepted in LOCAL-STORAGE, but a contained program referencing it still fails in the C compile, as in WORKING-STORAGE and as in bugs #870, because that pointer is declared inside the owning program's function.

It adds the testsuite case "GLOBAL in LOCAL-STORAGE" to run_fundamental.at, with ChangeLog entries. make check: 1373 expected, 9 skipped, 0 failed (1372 unpatched); the new test fails without the patch.

  • bugs #870: GLOBAL in LINKAGE, where the contained program's C code references a variable that exists only in the containing program; the same gap for linkage items.
  • bugs #958: its "LOCAL-STORAGE not allowed in nested programs" case, which the reply there calls "definitely a bug"; the other LOCAL-STORAGE restriction around nested programs.

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.

3 Attachments

Discussion


Log in to post a comment.