With the unmodified SDCC 4.6.2 #16889 snapshot dated 2026-09-18, targeting SM83 on Fedora 44, the following program (tentative.c) is rejected:
static const unsigned char value;
unsigned char read_value(void) { return value; }
static const unsigned char value = 3;
Compiled with:
sdcc -msm83 --std-c11 -S tentative.c
Compilation fails with:
tentative.c:3: error 0: Duplicate symbol 'value', symbol IGNORED
tentative.c:1: error 177: previously defined here
The expectation is that compilation should succeed. The first declaration is a tentative definition, and the final declaration supplies the initializer for the same object, and read_value() should return 3.
I noticed that removing const from both declarations makes the example compile correctly.
I have prepared a proposed fix against #16889, with regression tests.
In
defaultOClass, theS_CODEpath installs a synthetic zero initializer before the translation unit has been fully parsed. This makes the tentative definition appear initialized, soaddSymChainlater rejects the actual initialized definition as a duplicate.Removing that synthetic initializer alone is not sufficient. After functions ,
flushStatics()is called, which can emit the object before its later definition is encountered. The patch defers tentative objects during these early flushes and uses zero initialization at the end of processing a translation unit, during final emission. It also preserves custom constant-section placement.Validation on SM83 using ucgbz80: the full regression suite passed with 0 failures, 36,602 tests, and 6,409 test cases, using the snapshot runtime. The tentdecl diagnostic suite passed all 19 cases.
The patch also includes a separate regression for an uninitialized nested constant aggregate, previously rejected with “initialization needs curly braces.”, possibly related to https://sourceforge.net/p/sdcc/bugs/3121/
I have not tested other targets.