1: Sample code that reproduces the problem.
struct S; void f(struct S x) {(void)x;}
2: Exact command used to run SDCC on this sample code.
sdcc -mz80 --std=c2y --nostdinc -S incomplete-struct-param.c -o output.asm
3: SDCC version tested.
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15 TD- 4.6.4 #0 (Linux)
published under GNU General Public License (GPL)
Built from clean official SVN r16981 sources on Linux.
4: Observed and expected behaviour.
SDCC silently accepts the invalid examples on MCS51 with --stack-auto, Z80, Z180, R2K, R4K, SM83, TLCS-90, STM8 default/large and eZ80, plus Z80 C23. MCS51 default/large/medium, DS390, HC08, S08 and PDK13/14/15 diagnose them with error 66.
WG14 N3886,
6.7.7.4 paragraph 3, specifies the relevant constraint:
After adjustment, the parameters in a parameter type list in a function declarator that is part of a
definition of that function shall not have incomplete type.
The structure or union remains incomplete when passed by value. The body discards the parameter, or asks only for the size of a pointer to it, to avoid an unrelated unused-parameter warning. Complete aggregate parameters and a pointer to an incomplete structure are valid cases. A prototype-only declaration can use an incomplete parameter type; that distinction is important.
5: Additional checks.
Compiler Explorer: SDCC trunk and GCC 16.2 side by side.
Both panes use the sample above. SDCC uses -mz80 --std=c2y; GCC uses -std=c2y -pedantic-errors -fsyntax-only. Checked 7 October 2026: GCC diagnoses the constraint violation; SDCC accepts it without diagnostics. The CE trunk build reports SDCC 4.6.4 #16974.
GCC 13.3.0 locally (-std=c2x) and GCC 16.2.0 through Compiler Explorer (x86-64, cg162, -std=c2y) diagnose every invalid case and accept every control. Both used -pedantic-errors -fsyntax-only. No Clang or TCC comparison was run.
| Case | Expected | SDCC Z80 C2Y |
|---|---|---|
incomplete-struct-param.c |
Invalid | Accepted silently |
incomplete-union-param.c |
Invalid | Accepted silently |
incomplete-address-param.c |
Invalid | Accepted silently |
prototype-only-control.c |
Valid | Accepted silently |
array-adjustment-control.c |
Valid | Accepted silently |
complete-struct-control.c |
Valid | Accepted silently |
complete-union-control.c |
Valid | Accepted silently |
incomplete-pointer-control.c |
Valid | Accepted silently |
Configurations tested: MCS51 default/large/medium/stack-auto, DS390, Z80, Z180, Rabbit 2000/4000, SM83, TLCS-90, HC08, S08, STM8 default/large, PDK13/14/15, and eZ80. These are translation checks, not runtime tests.
Implementation observation: checkFunction checks completeness of the return type but does not perform the corresponding completeness check for each adjusted parameter. Some ports catch the problem later during parameter allocation; ports that do not allocate the parameter in that way accept it silently.
Please consider the attached candidate bug fix.
It checks by-value parameter completeness at function definitions before port-dependent allocation. Error 368 identifies the parameter position and function. Invalid definitions do not proceed to code generation; prototype-only declarations remain allowed.
The complete valdiag fixture set was compared on Z80, STM8 and three MCS51 configurations before and after applying the candidate patch.
Focused validation of this patch comprised 11 diagnostic cases on 7 configurations: incomplete structs/unions, later parameter positions, prototypes, complete types, pointers and adjusted array/function parameters. The 7 configurations are Z80, STM8, MCS51 default/large/stack-auto,
PDK14 and S08. All 77 checks passed.