1: Sample code that reproduces the problem.
int f(int p);
int main(void)
{
int i;
&f(0); // Clang & GCC: "not an lvalue" error
&(const int)i; // All: "not an lvalue error"
return 0;
}
2: Exact command used to run SDCC on this sample code
sdcc --std=c23 -c /work/bug8.c
3: SDCC version tested (type "sdcc -v" to find it)
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8/f8l TD- 4.5.21 #16327 (Linux)
4: Copy of the error message or incorrect output, or a clear description of the observed versus expected behavior.
In "Address and indirection operators" (6.5.4.2), C23 specifies the following constraint:
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
f(0) does not satisfy this constraint, and neither does (const int)i.
In "Diagnostics" (5.1.1.3), C23 specifies that:
A conforming implementation shall produce at least one diagnostic message (identified in an
implementation-defined manner) if a preprocessing translation unit or translation unit contains
a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as
undefined or implementation-defined.
(see https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf)
SDCC (correctly) produces the following diagnostic message about the expression &(const int)i:
/work/bug8.c:7: error 10: 'lvalue' required for 'address of' operation.
However, SDCC does not produce any diagnostic message about the expression &f(0), even though it is invalid for the same reason as &(const int)i.
I am aware that SDCC is not a conforming C23 compiler, but this inconsistency in production of diagnostic messages seems likely to be unintentional. Producing a diagnostic message in both situation might help programmers find errors more easily.
It appears that SDCC does treat function calls like lvalues in some situations, but I don't see how that could be useful:
char f(int p);
int main(void)
{
f(0) = 1; // error 10: 'lvalue' required for 'assignment' operation.
char *j = &f(0);
*j = 1; // equivalent, but no error
return 0;
}
If I delete the first assignment, SDCC produces the following code for MOS6502. It looks as though the char returned by f is misinterpreted as the low byte of a 16-bit address:
_main:
ldx #0x00 ; f(0);
txa ; f(0);
jsr _f ; f(0);
sta *(DPTR+0) ; j = &f(0) but _f returns char (in 'a') not an address!
stx *(DPTR+1) ; j = &f(0) but is the value of x predictable?
lda #0x01 ; = 1
ldy #0x00
sta [DPTR],y ; *j = 1
tya ; return 0
tax ; return 0
rts
If my interpretation is correct that bug that would have been avoided by implementing the diagnostic message needed for conformance with C23.
I meant to write "If my interpretation is correct then that bug would have been avoided by implementing the diagnostic message needed for conformance with C23."