typedef void Function(void);
void implicit_dereference(_Optional Function *pof)
{
pof();
}
void explicit_dereference(_Optional Function *pof)
{
(*pof)();
}
void guarded_implicit_dereference(_Optional Function *pof)
{
if (pof)
pof();
}
void guarded_explicit_dereference(_Optional Function *pof)
{
if (pof)
(*pof)();
}
sdcc -c --std=c23 test.c
No diagnostic output is produced.
An implementation that performs data-flow analysis is encouraged by the _Optional TS to diagnose dereference of a pointer to an optional-qualified type when its value cannot be proven non-null.
I therefore expected a diagnostic for both unguarded calls:
pof();
(*pof)();
The first call implicitly dereferences pof as part of applying the function-call operator; the second expresses that dereference explicitly. Neither pointer can be proven non-null.
No diagnostic is expected for either guarded call because the controlling if establishes that pof is non-null on the path containing the call.
The missing diagnostics are recommended rather than required, so their absence is not a mandatory-diagnostic conformance failure.
This case is derived from the anna example in support/valdiag/tests/_Optional-draft-2026-04-17.c, where the missing diagnostic is currently marked:
pof(); // recommended diagnostic /* IGNORE */ // BUG, should be warning!
The sample code given above deliberately avoids typeof, so this issue is independent of bugs #3916 and #3917.
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/huc6280/f8l TD- 4.6.2 #16838 (Linux)
I am attaching a proposed bugfix for this issue, created with assistance from Codex. I hope that it will prove acceptable when reviewed by SDCC's maintainers.
The main implementation question was whether to mark function calls as
isSemDerefor insert extra code to diagnose them separately. The second choice is more complex but I chose it anyway. Although an explicit function call such as(*f)()could pedantically be characterised as equivalent to(&(*f))()due to the ISO C rule that the call operator only acts on function pointers, not function designators, an implicit function call such asf()cannot be characterised thus. Also,isSemDerefdoesn’t seem to be used for all dereferences.I did the following testing of the proposed patch:
i.e.
make -j2
make -C support/regression clean-results
make -C support/regression -j2 test-ucz80
make -C support/valdiag clean
make -C support/valdiag -j2
Summary for 'ucz80': 0 failures, 36740 tests, 6407 test cases, 7347620 bytes, 1613638336 ticks
Summary for 'mcs51': 0 failures, 644 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'mcs51-large': 0 failures, 642 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'mcs51-stack-auto': 0 failures, 643 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'ds390': 0 failures, 630 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'z80': 0 failures, 633 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'z180': 0 failures, 632 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'r2k': 0 failures, 632 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'r4k': 0 failures, 632 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'sm83': 0 failures, 632 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'tlcs90': 0 failures, 632 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'hc08': 0 failures, 631 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 's08': 0 failures, 631 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'mos6502': 0 failures, 631 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'stm8': 0 failures, 634 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'f8': 0 failures, 630 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'pdk13': 0 failures, 633 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'pdk14': 0 failures, 631 tests, 366 test cases, 0 bytes, 0 ticks
Summary for 'pdk15': 0 failures, 629 tests, 366 test cases, 0 bytes, 0 ticks
Last edit: Christopher Bazley 2 days ago
See above.
The patch looks good to me.
For now, IMO we should wait a few days for the discussion on sdcc-devel on LLM use to settle.