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.
Unified · Split
| @@ -92,6 +92,7 @@ ST_FUNC void vpush(CType *type); · 91 unmodified lines | |||
| 92 | ST_FUNC int gvtst(int inv, int t); | 92 | ST_FUNC int gvtst(int inv, int t); |
| 93 | ST_FUNC int is_btype_size(int bt); | 93 | ST_FUNC int is_btype_size(int bt); |
| 94 | static void gen_inline_functions(TCCState *s); | 94 | static void gen_inline_functions(TCCState *s); |
| 95 | static void skip_or_save_block(TokenString **str); | ||
| 95 | 96 | ||
| 96 | ST_INLN int is_float(int t) | 97 | ST_INLN int is_float(int t) |
| 97 | { | 98 | { |
| @@ -4689,6 +4690,76 @@ ST_FUNC void unary(void) · 4591 unmodified lines | |||
| 4689 | next(); | 4690 | next(); |
| 4690 | break; | 4691 | break; |
| 4691 | 4692 | ||
| 4693 | case TOK_GENERIC: | ||
| 4694 | { | ||
| 4695 | CType controlling_type; | ||
| 4696 | int has_default = 0; | ||
| 4697 | int has_match = 0; | ||
| 4698 | CType cur_type; | ||
| 4699 | AttributeDef ad_tmp; | ||
| 4700 | int learn = 0; | ||
| 4701 | TokenString *str = NULL; | ||
| 4702 | ParseState saved_parse_state; | ||
| 4703 | |||
| 4704 | next(); | ||
| 4705 | skip('('); | ||
| 4706 | expr_type(&controlling_type, 1); | ||
| 4707 | if (controlling_type.t & VT_ARRAY) | ||
| 4708 | controlling_type.t = VT_PTR; | ||
| 4709 | controlling_type.t &= ~VT_CONSTANT; | ||
| 4710 | for (;;) { | ||
| 4711 | learn = 0; | ||
| 4712 | skip(','); | ||
| 4713 | if (tok == TOK_DEFAULT) { | ||
| 4714 | if (has_default) | ||
| 4715 | tcc_error("too many 'default'"); | ||
| 4716 | if (!has_match) { | ||
| 4717 | has_default = 1; | ||
| 4718 | learn = 1; | ||
| 4719 | } | ||
| 4720 | next(); | ||
| 4721 | } else { | ||
| 4722 | int itmp; | ||
| 4723 | |||
| 4724 | parse_btype(&cur_type, &ad_tmp); | ||
| 4725 | type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); | ||
| 4726 | if (compare_types(&controlling_type, &cur_type, 0)) { | ||
| 4727 | if (has_match) { | ||
| 4728 | tcc_error("type march twice"); | ||
| 4729 | } | ||
| 4730 | if (has_default) | ||
| 4731 | tok_str_free(str); | ||
| 4732 | has_match = 1; | ||
| 4733 | learn = 1; | ||
| 4734 | } | ||
| 4735 | } | ||
| 4736 | skip(':'); | ||
| 4737 | if (learn) { | ||
| 4738 | skip_or_save_block(&str); | ||
| 4739 | } else { | ||
| 4740 | skip_or_save_block(NULL); | ||
| 4741 | } | ||
| 4742 | if (tok == ',') | ||
| 4743 | continue; | ||
| 4744 | else if (tok == ')') | ||
| 4745 | break; | ||
| 4746 | } | ||
| 4747 | if (!has_match && !has_default) { | ||
| 4748 | char buf[256]; | ||
| 4749 | |||
| 4750 | type_to_str(buf, 256, &controlling_type, NULL); | ||
| 4751 | tcc_error("_Generic sellector of type '%s' is not compatible with any assosiation", | ||
| 4752 | buf); | ||
| 4753 | } | ||
| 4754 | skip(')'); | ||
| 4755 | save_parse_state(&saved_parse_state); | ||
| 4756 | begin_macro(str, 1); | ||
| 4757 | next(); | ||
| 4758 | expr_eq(); | ||
| 4759 | end_macro(); | ||
| 4760 | restore_parse_state(&saved_parse_state); | ||
| 4761 | break; | ||
| 4762 | } | ||
| 4692 | // special qnan , snan and infinity values | 4763 | // special qnan , snan and infinity values |
| 4693 | case TOK___NAN__: | 4764 | case TOK___NAN__: |
| 4694 | vpush64(VT_DOUBLE, 0x7ff8000000000000ULL); | 4765 | vpush64(VT_DOUBLE, 0x7ff8000000000000ULL); |
| @@ -36,7 +36,9 @@ · 35 unmodified lines | |||
| 36 | DEF(TOK_RESTRICT2, "__restrict") | 36 | DEF(TOK_RESTRICT2, "__restrict") |
| 37 | DEF(TOK_RESTRICT3, "__restrict__") | 37 | DEF(TOK_RESTRICT3, "__restrict__") |
| 38 | DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */ | 38 | DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */ |
| 39 | 39 | ||
| 40 | DEF(TOK_GENERIC, "_Generic") | ||
| 41 | |||
| 40 | DEF(TOK_FLOAT, "float") | 42 | DEF(TOK_FLOAT, "float") |
| 41 | DEF(TOK_DOUBLE, "double") | 43 | DEF(TOK_DOUBLE, "double") |
| 42 | DEF(TOK_BOOL, "_Bool") | 44 | DEF(TOK_BOOL, "_Bool") |