When trying to compile the examples from DR 481 about _Generic, none of them work.
This is expected for those examples that contain compound literals, because SDCC does not support them, and for the second one, provided that SDCC's _Generic implementation is correct, but IMO the first one should work and the second one should fail with a different error message.
This is the full set of examples:
char const* a = _Generic("bla", char*: "blu"); // clang error
// char const* b = _Generic("bla", char[4]: "blu"); // gcc error
// char const* c = _Generic((int const){ 0 }, int: "blu"); // clang error
// char const* d = _Generic((int const){ 0 }, int const: "blu"); // gcc error
// char const* e = _Generic(+(int const){ 0 }, int: "blu"); // both ok
// char const* f = _Generic(+(int const){ 0 }, int const: "blu"); // both error
The exact command line was:
:~/sdcc-code> sdcc/bin/sdcc -c generic_test.c
The SDCC version was 4.0.4 rev. 11930.
The first example results in this error message:
generic_test.c:1: error 229: no matching expression in generic association
generic_test.c:1: error 9: FATAL Compiler Internal Error in file 'SDCCast.c' line number '1808' : unexpected link in expression tree
Contact Author with source code
generic_test.c:1: error 2: Initializer element is not a constant expression
The second example results in this error message:
Internal error: validateLink failed in SPEC_NOUN(type) @ SDCCast.c:5424: expected SPECIFIER, got DECLARATOR
The remaining examples result in this error message:
generic_test.c:3: error 254: compound literals require ISO C99 or later and are not implemented
Looks like we have two bugs here:
1) When there is no match, there is no result of the _Generic, but apparently a further stage (initialization) still tries to use it. When there is no match, and no default, an error flag is set, but apparently there is some place that doesn't check or forward the error flag correctly.
This bug can even be shown by a simple
int i = _Generic(7, char : 7);2) Implicit named address spaces. See the following:
We get no match, since SDCC (when compiling with default options, i.e. for mcs51 small memory model). places i in __near space, and considers &i to be of type __near int *, which doesn't match int *. I guess we need to clearly separate the case of an explicit user-supplied address space vs. the case of a compiler-deduced address space to be able to fix this bug.
Regarding 2),
I get the same error message, i.e. "no matching expression in generic association", for STM8 and Z80. Do these ports even have implicitly named address spaces?
The ports don't really have it, but the SDCC frontend nevertheless attached these to some things (I guess due to mcs51 being the fist backend historically). E.g. compiling for stm8
with some debug printfs added in SDCCast.c, I see:
1) is fixed in [r13378].
Related
Commit: [r13378]
Another issue is that SDCC implicitly makes string literals const char [] instead of char *. Before _Generic this wasn't much of an issue, but it is now. I guess we need a flag for implicit const, like we have for implicit (un)signed of char.
Last edit: Philipp Klaus Krause 2022-04-19
Hmm.The string constant non-match still gives
When compiling for mcs51. I seem to remember having fixed such an issue (i.e. the internal error) just few weeks ago (though AFAIR, I only tested on stm8).
P.S.: This aspect is fixed in [r13391]. The fix is similar to the one 10 days ago.
Related
Commit: [r13391]
Last edit: Philipp Klaus Krause 2022-04-20
This works now in the intrinsicnamedaddressspaces branch.
But I suspect there are still some more corner cases similar to this one that I need to look into. Once it looks reasonably complete, I'll merge to trunk#, if there are no regressions.
As of [r13402], the fix is in trunk.
Related
Commit: [r13402]
Awesome!