mirror of https://github.com/rui314/chibicc
Add _Generic
This commit is contained in:
parent
1433b404d6
commit
1faab48ecf
47
parse.c
47
parse.c
|
@ -2605,12 +2605,56 @@ static Node *funcall(Token **rest, Token *tok, Node *fn) {
|
|||
return node;
|
||||
}
|
||||
|
||||
// generic-selection = "(" assign "," generic-assoc ("," generic-assoc)* ")"
|
||||
//
|
||||
// generic-assoc = type-name ":" assign
|
||||
// | "default" ":" assign
|
||||
static Node *generic_selection(Token **rest, Token *tok) {
|
||||
Token *start = tok;
|
||||
tok = skip(tok, "(");
|
||||
|
||||
Node *ctrl = assign(&tok, tok);
|
||||
add_type(ctrl);
|
||||
|
||||
Type *t1 = ctrl->ty;
|
||||
if (t1->kind == TY_FUNC)
|
||||
t1 = pointer_to(t1);
|
||||
else if (t1->kind == TY_ARRAY)
|
||||
t1 = pointer_to(t1->base);
|
||||
|
||||
Node *ret = NULL;
|
||||
|
||||
while (!consume(rest, tok, ")")) {
|
||||
tok = skip(tok, ",");
|
||||
|
||||
if (equal(tok, "default")) {
|
||||
tok = skip(tok->next, ":");
|
||||
Node *node = assign(&tok, tok);
|
||||
if (!ret)
|
||||
ret = node;
|
||||
continue;
|
||||
}
|
||||
|
||||
Type *t2 = typename(&tok, tok);
|
||||
tok = skip(tok, ":");
|
||||
Node *node = assign(&tok, tok);
|
||||
if (is_compatible(t1, t2))
|
||||
ret = node;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
error_tok(start, "controlling expression type not compatible with"
|
||||
" any generic association type");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// primary = "(" "{" stmt+ "}" ")"
|
||||
// | "(" expr ")"
|
||||
// | "sizeof" "(" type-name ")"
|
||||
// | "sizeof" unary
|
||||
// | "_Alignof" "(" type-name ")"
|
||||
// | "_Alignof" unary
|
||||
// | "_Generic" generic-selection
|
||||
// | "__builtin_types_compatible_p" "(" type-name, type-name, ")"
|
||||
// | "__builtin_reg_class" "(" type-name ")"
|
||||
// | ident
|
||||
|
@ -2657,6 +2701,9 @@ static Node *primary(Token **rest, Token *tok) {
|
|||
return new_ulong(node->ty->align, tok);
|
||||
}
|
||||
|
||||
if (equal(tok, "_Generic"))
|
||||
return generic_selection(rest, tok->next);
|
||||
|
||||
if (equal(tok, "__builtin_types_compatible_p")) {
|
||||
tok = skip(tok->next, "(");
|
||||
Type *t1 = typename(&tok, tok);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#include "test.h"
|
||||
|
||||
int main() {
|
||||
ASSERT(1, _Generic(100.0, double: 1, int *: 2, int: 3, float: 4));
|
||||
ASSERT(2, _Generic((int *)0, double: 1, int *: 2, int: 3, float: 4));
|
||||
ASSERT(2, _Generic((int[3]){}, double: 1, int *: 2, int: 3, float: 4));
|
||||
ASSERT(3, _Generic(100, double: 1, int *: 2, int: 3, float: 4));
|
||||
ASSERT(4, _Generic(100f, double: 1, int *: 2, int: 3, float: 4));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue