cobc refuses an arithmetic expression in SET index-name TO, SET index-name UP BY / DOWN BY and SET data-pointer UP / DOWN BY. A single operand works; any operator is a syntax error. This is a request to accept it; the attached patch implements it.
setexpr.cob (attached):
IDENTIFICATION DIVISION.
PROGRAM-ID. SETEXPR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 N PIC 9 VALUE 2.
01 T VALUE "ABCDEFGHI".
05 E PIC X OCCURS 9 TIMES INDEXED BY X Y.
01 P USAGE POINTER.
01 C PIC X BASED.
PROCEDURE DIVISION.
SET X Y TO N + 3
DISPLAY E (X) E (Y)
SET X UP BY N * 2
DISPLAY E (X)
SET X DOWN BY N - 1
DISPLAY E (X)
SET P TO ADDRESS OF T
SET P UP BY N * 3
SET ADDRESS OF C TO P
DISPLAY C
STOP RUN.
cobc -std=cobol2014 -x setexpr.cob && ./setexpr
3.2.0 and 3.3-dev r5751 both stop with
setexpr.cob:11: error: syntax error, unexpected +
setexpr.cob:13: error: syntax error, unexpected *
setexpr.cob:15: error: syntax error, unexpected -
setexpr.cob:18: error: syntax error, unexpected *
each followed by its source excerpt. The result is the same with -std=cobol2002, default, ibm and mf. As a workaround, SET X TO FUNCTION INTEGER (N + 3) works on both.
Under -std=cobol2002 and -std=cobol2014 the program should print EE, I and H (occurrences 5, 9 and 8), then G (6 bytes into T). ISO/IEC 1989:2023 14.9.39.2 gives Formats 1, 2 and 10 (data-pointer-arithmetic) an arithmetic-expression operand. By general rule 2 a) 1. c. of 14.9.39.4, "index-name-1 is set to a value causing it to refer to the table element that would correspond in occurrence number to that expression"; by general rule 20, the pointer moves by that many bytes. The formats are the same in 2002 (where Format 10 is Format 9) and in the 2014 FCD.
In cobc/parser.y, set_to (target_x_list TO x) and set_up_down (target_x_list up_or_down BY x) take an x, a single operand, not the exp that subscripts and COMPUTE use. The code behind them, cb_emit_set_to (cb_build_move) and cb_emit_set_up_down (cb_build_add / cb_build_sub), already handles an expression.
The attached n10-set-index-expression.patch (against 3.3-dev r5751) gives both rules a new set_x: an exp, or one of the non-arithmetic forms of x. The grammar stays conflict-free; a single operand compiles to the same C. In typeck.c, the new cb_check_set_arith_expr accepts a non-constant expression only for an index-name, or a data-pointer after UP BY / DOWN BY (syntax rules 1 to 4 and 23), and marks it BOP_RESOLVE_AS_INTEGER, as cb_build_identifier does for a subscript. Two things to weigh: a non-integer result is truncated, as for a subscript or a single operand, instead of raising EC-BOUND-SUBSCRIPT or EC-SIZE-ADDRESS; and one UP BY may still mix index-names and pointers, as it may with a single operand.
Patched, setexpr prints that output. The patch adds the testsuite cases "SET index / pointer by arithmetic expression" to run_misc.at and "SET TO / UP BY arithmetic expression, invalid target" to syn_set.at, with ChangeLog entries. make check: 1374 expected, 9 skipped, 0 failed (1372 unpatched); the new tests fail without the patch. The NIST suite results are unchanged.
bugs #866: SET of an index raises none of the exception conditions of Formats 1 and 2, the truncation above included.
bugs #228: the SET target check accepts any numeric item; the patch leaves single operands as they are.
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.