https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/
In spite of _Generic being a compile-time type switch, the unused
clauses all have to type check with a given argument.
E.g. any of the cases maps an argument x to (x)->memb, then
the argument cannot be a "char *".
_Generic should only require that the clauses parse, using
the minimal amount of type information to that aim,.
(If the clauses don't parse, they cannot be identified,
so the construct cannot work. When sscanning the association
list, when the implementation encounters a nonmatching type,
it has to parse the associatead expression in order to find
the next clause in the association list.)
I would havce designed this with required parentheses:
_Generic(expr, t1: (e1), t2: (e2), ... :default (edfl));
Only the matching expression would be fully parsed; the non-matching
ones would be regarded as token sequences in which parentheses and
braces have to balance.
On 2023-07-30, Kaz Kylheku wrote:I usually do this why a pointer to void and back to the right type
https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/
In spite of _Generic being a compile-time type switch, the unused
clauses all have to type check with a given argument.
E.g. any of the cases maps an argument x to (x)->memb, then
the argument cannot be a "char *".
_Generic should only require that the clauses parse, using
the minimal amount of type information to that aim,.
(If the clauses don't parse, they cannot be identified,
so the construct cannot work. When sscanning the association
list, when the implementation encounters a nonmatching type,
it has to parse the associatead expression in order to find
the next clause in the association list.)
I would havce designed this with required parentheses:
_Generic(expr, t1: (e1), t2: (e2), ... :default (edfl));
Only the matching expression would be fully parsed; the non-matchingAnother idea is to parse and type check each of the en, but inside each
ones would be regarded as token sequences in which parentheses and
braces have to balance.
one, pretend that expr has the type of tn.
We invent a generated symbol __g0025 and transform
the construct like this. Here I'm using GCC brace expression
syntax ({ ... }):
_Generic(expr,
t1 : ({t1 __g0025 = expr; ee1; }),
t2 : ({t2 __g0025 = expr; ee2; }),
// ...)
Here ee2 denotes e1, but with __g0025 substituted for
expr (so that expr is evaluated only once).
Under this transformation, the ony type error we have
in the dead clauses occurs in the initialization of
__g0025 which isn't compatible with tn on the left.
The implementation can arrange to suppress that
diagnostic, and then just parse and type-check ee2, which has a
correctly typed __g0025 in scope.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,030 |
Nodes: | 10 (0 / 10) |
Uptime: | 96:11:42 |
Calls: | 13,353 |
Calls today: | 2 |
Files: | 186,574 |
D/L today: |
25,244 files (7,162M bytes) |
Messages: | 3,359,460 |