patch type_to_str to handle complex function-ptr decls better

Code like:

    #include <signal.h>
    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]
This commit is contained in:
Petr Skocik 2018-03-16 00:26:16 +01:00 committed by Michael Matz
parent f0a25ca263
commit d6d3cf00ec
3 changed files with 27 additions and 8 deletions

View File

@ -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(',');

View File

@ -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;
}

View File

@ -10,4 +10,5 @@
3
4
long
1
1
3