aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccgen.c71
-rw-r--r--tcctok.h4
2 files changed, 74 insertions, 1 deletions
diff --git a/tccgen.c b/tccgen.c
index 304225e..af8d2a7 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -92,6 +92,7 @@ ST_FUNC void vpush(CType *type);
ST_FUNC int gvtst(int inv, int t);
ST_FUNC int is_btype_size(int bt);
static void gen_inline_functions(TCCState *s);
+static void skip_or_save_block(TokenString **str);
ST_INLN int is_float(int t)
{
@@ -4689,6 +4690,76 @@ ST_FUNC void unary(void)
next();
break;
+ case TOK_GENERIC:
+ {
+ CType controlling_type;
+ int has_default = 0;
+ int has_match = 0;
+ CType cur_type;
+ AttributeDef ad_tmp;
+ int learn = 0;
+ TokenString *str = NULL;
+ ParseState saved_parse_state;
+
+ next();
+ skip('(');
+ expr_type(&controlling_type, 1);
+ if (controlling_type.t & VT_ARRAY)
+ controlling_type.t = VT_PTR;
+ controlling_type.t &= ~VT_CONSTANT;
+ for (;;) {
+ learn = 0;
+ skip(',');
+ if (tok == TOK_DEFAULT) {
+ if (has_default)
+ tcc_error("too many 'default'");
+ if (!has_match) {
+ has_default = 1;
+ learn = 1;
+ }
+ next();
+ } else {
+ int itmp;
+
+ parse_btype(&cur_type, &ad_tmp);
+ type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT);
+ if (compare_types(&controlling_type, &cur_type, 0)) {
+ if (has_match) {
+ tcc_error("type march twice");
+ }
+ if (has_default)
+ tok_str_free(str);
+ has_match = 1;
+ learn = 1;
+ }
+ }
+ skip(':');
+ if (learn) {
+ skip_or_save_block(&str);
+ } else {
+ skip_or_save_block(NULL);
+ }
+ if (tok == ',')
+ continue;
+ else if (tok == ')')
+ break;
+ }
+ if (!has_match && !has_default) {
+ char buf[256];
+
+ type_to_str(buf, 256, &controlling_type, NULL);
+ tcc_error("_Generic sellector of type '%s' is not compatible with any assosiation",
+ buf);
+ }
+ skip(')');
+ save_parse_state(&saved_parse_state);
+ begin_macro(str, 1);
+ next();
+ expr_eq();
+ end_macro();
+ restore_parse_state(&saved_parse_state);
+ break;
+ }
// special qnan , snan and infinity values
case TOK___NAN__:
vpush64(VT_DOUBLE, 0x7ff8000000000000ULL);
diff --git a/tcctok.h b/tcctok.h
index 270c1ed..56e1ae3 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -36,7 +36,9 @@
DEF(TOK_RESTRICT2, "__restrict")
DEF(TOK_RESTRICT3, "__restrict__")
DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
-
+
+ DEF(TOK_GENERIC, "_Generic")
+
DEF(TOK_FLOAT, "float")
DEF(TOK_DOUBLE, "double")
DEF(TOK_BOOL, "_Bool")