From d6d3cf00ec37368fd885cf50191c87761e6c49e8 Mon Sep 17 00:00:00 2001 From: Petr Skocik Date: Fri, 16 Mar 2018 00:26:16 +0100 Subject: [PATCH] patch type_to_str to handle complex function-ptr decls better Code like: #include int main() { _Generic(signal, int: 0); } should fail with error: type 'extern void (*(int, void (*)(int)))(int)' does not match any association not error: type 'extern void *(int)(int, void *(int))' does not match any association [matz: fix formatting, fix function-to-pointer decay for operands of _Generic, add testcase for this] --- tccgen.c | 24 +++++++++++++++++------- tests/tests2/94_generic.c | 8 ++++++++ tests/tests2/94_generic.expect | 3 ++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tccgen.c b/tccgen.c index a852375..7ed89ac 100644 --- a/tccgen.c +++ b/tccgen.c @@ -19,7 +19,6 @@ */ #include "tcc.h" - /********************************************************/ /* global variables */ @@ -2938,17 +2937,26 @@ static void type_to_str(char *buf, int buf_size, break; case VT_FUNC: s = type->ref; - type_to_str(buf, buf_size, &s->type, varstr); - pstrcat(buf, buf_size, "("); + buf1[0]=0; + if (varstr && '*' == *varstr) { + pstrcat(buf1, sizeof(buf1), "("); + pstrcat(buf1, sizeof(buf1), varstr); + pstrcat(buf1, sizeof(buf1), ")"); + } + pstrcat(buf1, buf_size, "("); sa = s->next; while (sa != NULL) { - type_to_str(buf1, sizeof(buf1), &sa->type, NULL); - pstrcat(buf, buf_size, buf1); + char buf2[256]; + type_to_str(buf2, sizeof(buf2), &sa->type, NULL); + pstrcat(buf1, sizeof(buf1), buf2); sa = sa->next; if (sa) - pstrcat(buf, buf_size, ", "); + pstrcat(buf1, sizeof(buf1), ", "); } - pstrcat(buf, buf_size, ")"); + if (s->f.func_type == FUNC_ELLIPSIS) + pstrcat(buf1, sizeof(buf1), ", ..."); + pstrcat(buf1, sizeof(buf1), ")"); + type_to_str(buf, buf_size, &s->type, buf1); goto no_var; case VT_PTR: s = type->ref; @@ -5005,6 +5013,8 @@ ST_FUNC void unary(void) skip('('); expr_type(&controlling_type, expr_eq); controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY); + if ((controlling_type.t & VT_BTYPE) == VT_FUNC) + mk_pointer(&controlling_type); for (;;) { learn = 0; skip(','); diff --git a/tests/tests2/94_generic.c b/tests/tests2/94_generic.c index d7fb5fc..4804f65 100644 --- a/tests/tests2/94_generic.c +++ b/tests/tests2/94_generic.c @@ -20,6 +20,12 @@ int b_f() return 10; } +typedef int (*fptr)(int); +int foo(int i) +{ + return i; +} + typedef int int_type1; #define gen_sw(a) _Generic(a, const char *: 1, default: 8, int: 123); @@ -60,5 +66,7 @@ int main() long long: "long long")); i = _Generic(l, long: 1, int: 2); printf("%d\n", i); + i = _Generic(foo, fptr: 3, int: 4); + printf("%d\n", i); return 0; } diff --git a/tests/tests2/94_generic.expect b/tests/tests2/94_generic.expect index 9aa9275..748d78f 100644 --- a/tests/tests2/94_generic.expect +++ b/tests/tests2/94_generic.expect @@ -10,4 +10,5 @@ 3 4 long -1 \ No newline at end of file +1 +3