mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
Treat func pointers with different return types as not compatible
Tcc considered function ptrs with different return types to be compatible which disallowed some otherwise valid operations like: `_Generic(foo, int(*)():0, void(*)(void):1)` which would fail to compile with a error message of "type match twice" This changed also required longjump's return type to be void and munmap's to be int to be compatible with standard headers.
This commit is contained in:
parent
3b1a42e734
commit
3709f8de14
21
tccgen.c
21
tccgen.c
@ -80,7 +80,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
|
||||
ST_DATA int func_vc;
|
||||
static int last_line_num, new_file, func_ind; /* debug info control */
|
||||
ST_DATA const char *funcname;
|
||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
|
||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type, func_mem_move, void_type, void_ptr_type;
|
||||
static CString initstr;
|
||||
|
||||
#if PTR_SIZE == 4
|
||||
@ -800,6 +800,14 @@ ST_FUNC void tccgen_init(TCCState *s1)
|
||||
char_pointer_type = char_type;
|
||||
mk_pointer(&char_pointer_type);
|
||||
|
||||
void_type.t = VT_VOID;
|
||||
void_ptr_type = void_type;
|
||||
mk_pointer(&void_ptr_type);
|
||||
func_mem_move.t = VT_FUNC;
|
||||
func_mem_move.ref = sym_push(SYM_FIELD, &void_ptr_type, 0, 0);
|
||||
func_mem_move.ref->f.func_call = FUNC_CDECL;
|
||||
func_mem_move.ref->f.func_type = FUNC_OLD;
|
||||
|
||||
func_old_type.t = VT_FUNC;
|
||||
func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
|
||||
func_old_type.ref->f.func_call = FUNC_CDECL;
|
||||
@ -3029,16 +3037,11 @@ static int is_compatible_func(CType *type1, CType *type2)
|
||||
&& s1->f.func_type != FUNC_OLD
|
||||
&& s2->f.func_type != FUNC_OLD)
|
||||
return 0;
|
||||
/* we should check the function return type for FUNC_OLD too
|
||||
but that causes problems with the internally used support
|
||||
functions such as TOK_memmove */
|
||||
if (s1->f.func_type == FUNC_OLD && !s1->next)
|
||||
return 1;
|
||||
if (s2->f.func_type == FUNC_OLD && !s2->next)
|
||||
return 1;
|
||||
for (;;) {
|
||||
if (!is_compatible_unqualified_types(&s1->type, &s2->type))
|
||||
return 0;
|
||||
if (s1->f.func_type == FUNC_OLD || s2->f.func_type == FUNC_OLD )
|
||||
return 1;
|
||||
s1 = s1->next;
|
||||
s2 = s2->next;
|
||||
if (!s1)
|
||||
@ -3907,7 +3910,7 @@ ST_FUNC void vstore(void)
|
||||
else
|
||||
#endif
|
||||
/* Use memmove, rather than memcpy, as dest and src may be same: */
|
||||
vpush_global_sym(&func_old_type, TOK_memmove);
|
||||
vpush_global_sym(&func_mem_move, TOK_memmove);
|
||||
|
||||
vswap();
|
||||
/* source */
|
||||
|
4
tccpp.c
4
tccpp.c
@ -3721,10 +3721,10 @@ static void tcc_predefs(CString *cstr)
|
||||
"__BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))\n"
|
||||
#endif
|
||||
"__BUILTIN(void,abort,(void))\n"
|
||||
"__BOUND(int,longjmp,())\n"
|
||||
"__BOUND(void,longjmp,())\n"
|
||||
#ifndef TCC_TARGET_PE
|
||||
"__BOUND(void*,mmap,())\n"
|
||||
"__BOUND(void*,munmap,())\n"
|
||||
"__BOUND(int,munmap,())\n"
|
||||
#endif
|
||||
"#undef __BUILTINBC\n"
|
||||
"#undef __BUILTIN\n"
|
||||
|
@ -21,10 +21,12 @@ int b_f()
|
||||
}
|
||||
|
||||
typedef int (*fptr)(int);
|
||||
typedef void (*vfptr)(int);
|
||||
int foo(int i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
void void_foo(int i) {}
|
||||
|
||||
typedef int int_type1;
|
||||
|
||||
@ -66,7 +68,9 @@ int main()
|
||||
long long: "long long"));
|
||||
i = _Generic(l, long: 1, int: 2);
|
||||
printf("%d\n", i);
|
||||
i = _Generic(foo, fptr: 3, int: 4);
|
||||
i = _Generic(foo, fptr: 3, int: 4, vfptr: 5);
|
||||
printf("%d\n", i);
|
||||
i = _Generic(void_foo, fptr: 3, int: 4, vfptr: 5);
|
||||
printf("%d\n", i);
|
||||
|
||||
(void)_Generic((int(*)[2]){0}, int(*)[2]:0, int(*)[4]:0); //shouldn't match twice
|
||||
|
@ -12,3 +12,4 @@
|
||||
long
|
||||
1
|
||||
3
|
||||
5
|
||||
|
Loading…
Reference in New Issue
Block a user