Compiling the following code generates two warnings and finally broken code:
typedef char * PCHAR;
char KAR;
PCHAR foo(void) reentrant //this fails
{
return &KAR;
}
PCHAR bar(void) // this is ok
{
return &KAR;
}
sdcc -c bug.c
bug.c:7: warning 60: function return value mismatch from type 'char near* '
to type 'char generic* unknown type'
bug.c:5: warning 59: function 'foo' must return value
Used SDCC 2.6.1 #4471
;------------------------------------------------------------
; bug.c:5: PCHAR foo(void) reentrant //this fails
; -----------------------------------------
; function foo
; -----------------------------------------
_foo:
; bug.c:7: return &KAR; <<<<< NO CODE GENERATED
; Peephole 300 removed redundant label 00101$
ret
;------------------------------------------------------------
;Allocation info for local variables in function 'bar'
;------------------------------------------------------------
;------------------------------------------------------------
; bug.c:10: PCHAR bar(void) // this is ok
; -----------------------------------------
; function bar
; -----------------------------------------
_bar:
; bug.c:12: return &KAR;
; genRet
; Peephole 182.a used 16 bit load of DPTR
mov dptr,#_KAR
mov b,#0x40
; Peephole 300 removed redundant label 00101$
ret
Logged In: YES
user_id=888171
Originator: YES
Fixed in SDCC 2.6.2 #4503.
Apparently, for practical purposes, the fix works, but it relies on undefined behaviour:
newLink() writes members of sym_link, after allocating it with calloc(). By 6.2.6.1p6 of N2455 at that time the padding bytes in sym_link take unspecified values, so the return memcmp() might tell us that the two sym_link are different, even when they have just been obtained from newLink() and not written otherwise.
Are you saying that instead of
!memcmp(sym->type->next, empty)
we should usesym->type->next == empty
? I think that fixing that would have been easier than finding this bug and reopening it.One one hand I hesitated to make a change inside another developer's bugfix, on the other hand, there is no == for aggregate types.
Last edit: Philipp Klaus Krause 2020-05-23
Huh? There is no == to compare struct variables? Or do you mean that there isn't one when there is a union inside the struct?
Btw. It seems the fix can be dropped now as it has been fixed somewhere else as well. When I remove it, all regression tests still pass. It seems there is none for this particular case, which I will add.
Yes. See e.g. section 6.5.9 of the N2479 standard draft.
The operands to == and != need to be arithmetic types or pointers.