From 157bad52cdb052015f64a29e47099b2470f67c3e Mon Sep 17 00:00:00 2001 From: Matthias Gatto Date: Fri, 9 Dec 2016 11:42:41 +0100 Subject: [PATCH] add C11's _Generic Simple implementation, I'm not even sure to respect C standart here, but it should work with most use case. This add an case in unary(), and generate TokString depending of _Generic controlling exression, use begin_macro to "push" the generated TokString, then call unary() again before exiting the switch so the just add token are reevaluate again. --- tccgen.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tcctok.h | 4 +++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tccgen.c b/tccgen.c index 304225e8..af8d2a71 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 270c1edf..56e1ae31 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")