1: Sample code that reproduces the problem.
struct S { int (*x)[]; };
struct S { int (*x)[2]; };
2: Exact command used to run SDCC on this sample code.
/workspace/scratch/babc9a325375/closure-r16981/bin/sdcc -mz80 --std=c2y --nostdinc -S /workspace/scratch/babc9a325375/c2y-discovery-7/confirmed/repeated-member-types-sample.c -o /workspace/scratch/babc9a325375/c2y-discovery-7/sample-results/repeated-member-types/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)
It was compiled from clean official SVN r16981 sources on Linux.
4: Observed and expected behaviour.
Repeated definitions of the same tagged structure or union require corresponding member types to be the same, not merely compatible. Pointer-to-incomplete-array and pointer-to-known-size-array types are compatible but are not the same type. SDCC silently accepts changing between them in either direction. It also accepts changed const/volatile qualification of members and pointer targets, which additionally violates compatibility requirements. Identical repeated definitions, including typedef aliases for the same member type, are valid in C23/C2Y. A changed int/char member is correctly diagnosed. GCC 16.2 accepts the valid cases and diagnoses the invalid ones.
WG14 N3886,
6.7.3.4 paragraph 1, specifies these constraints:
Where two declarations that use the same tag declare the same type, they shall both use the same choice of struct, union, or enum. If two declarations of the same type have a member-declaration or enumerator-list, one shall not be nested within the other and both declarations shall fulfill all requirements of compatible types (6.2.7) with the additional requirement that corresponding members of structure or union types shall have the same (and not merely compatible) types.
A diagnostic is required for constraint violations.
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: SDCC
accepts the sample without diagnostics; GCC diagnoses it. CE's trunk selection reported SDCC 4.6.4 #16974.
The focused test matrix used 19 C2Y configurations plus Z80 C23. Every valid case compiled without diagnostics. GCC 16.2 diagnosed every invalid case and accepted every control.
| Case | Expected | SDCC Z80 C2Y |
|---|---|---|
repeat-struct-const.c |
Invalid | Accepted silently |
repeat-struct-volatile.c |
Invalid | Accepted silently |
repeat-union-const.c |
Invalid | Accepted silently |
repeat-pointer-pointee-const.c |
Invalid | Accepted silently |
repeat-pointer-const.c |
Invalid | Accepted silently |
repeat-array-composite.c |
Invalid | Accepted silently |
repeat-array-composite-reverse.c |
Invalid | Accepted silently |
repeat-plain-control.c |
Valid | Accepted silently |
repeat-const-control.c |
Valid | Accepted silently |
repeat-typedef-control.c |
Valid | Accepted silently |
repeat-different-type.c |
Invalid | Error 210 |
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. Translation/diagnostic checks only; no runtime result is claimed.
Implementation observation: The redefinition loop in src/SDCC.y calls compareType on corresponding fields. That comparison does not enforce the same-type requirement and also accepts the qualification changes exercised here.
Please consider the attached candidate patch.
Compatible member types are insufficient for repeated structure or union definitions. Compare exact types, including array bounds and qualifiers. Check qualifiers before the bit-precise type comparison returns, so
constandvolatileon those member types are not overlooked.Testing: 161 diagnostic checks passed. Diagnostic configurations: Z80, STM8, MCS51, MCS51 large, MCS51 stack-auto, PDK14, S08. All focused checks passed. The counts include positive controls as well as expected diagnostics.