mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-08 12:28:40 +08:00
tccgen.c: fix two scope problems
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
... see tests Also: - tccgen.c: cleanup _Generic a little - libtcc.c: cleanup mem-debug a little - arm-link.c: read/write only once - tcc.h: another fix for clang offsetof - tccdbg.c: * stabs: handle forward struct/enum decls * stabs: fix anonymous struct members (must not have a .L123 name) * avoid strncpy()
This commit is contained in:
parent
4e6c4db340
commit
acb2a909dd
17
arm-link.c
17
arm-link.c
@ -194,17 +194,18 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
case R_ARM_PLT32:
|
case R_ARM_PLT32:
|
||||||
{
|
{
|
||||||
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
|
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
|
||||||
x = read32le(ptr) & 0xffffff;
|
unsigned code = read32le(ptr);
|
||||||
|
x = code & 0x00ffffff;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
|
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
|
||||||
#endif
|
#endif
|
||||||
write32le(ptr, read32le(ptr) & 0xff000000);
|
code &= 0xff000000;
|
||||||
if (x & 0x800000)
|
x <<= 2;
|
||||||
x -= 0x1000000;
|
if (x & 0x2000000)
|
||||||
x = (unsigned) x << 2;
|
x -= 0x4000000;
|
||||||
blx_avail = (CONFIG_TCC_CPUVER >= 5);
|
blx_avail = (CONFIG_TCC_CPUVER >= 5);
|
||||||
is_thumb = val & 1;
|
is_thumb = val & 1;
|
||||||
is_bl = read32le(ptr) >> 24 == 0xeb;
|
is_bl = code == 0xeb000000;
|
||||||
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
|
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
|
||||||
x += val - addr;
|
x += val - addr;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
@ -220,9 +221,9 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
/* Only reached if blx is avail and it is a call */
|
/* Only reached if blx is avail and it is a call */
|
||||||
if (is_thumb) {
|
if (is_thumb) {
|
||||||
x |= h << 24;
|
x |= h << 24;
|
||||||
write32le(ptr, 0xfa << 24); /* bl -> blx */
|
code = 0xfa000000; /* bl -> blx */
|
||||||
}
|
}
|
||||||
write32le(ptr, read32le(ptr) | x);
|
write32le(ptr, code | x);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
/* Since these relocations only concern Thumb-2 and blx instruction was
|
/* Since these relocations only concern Thumb-2 and blx instruction was
|
||||||
|
|||||||
7
libtcc.c
7
libtcc.c
@ -326,7 +326,7 @@ struct mem_debug_header {
|
|||||||
struct mem_debug_header *prev;
|
struct mem_debug_header *prev;
|
||||||
struct mem_debug_header *next;
|
struct mem_debug_header *next;
|
||||||
int line_num;
|
int line_num;
|
||||||
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
char file_name[MEM_DEBUG_FILE_LEN];
|
||||||
unsigned magic2;
|
unsigned magic2;
|
||||||
ALIGNED(16) unsigned char magic3[4];
|
ALIGNED(16) unsigned char magic3[4];
|
||||||
};
|
};
|
||||||
@ -367,9 +367,8 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
|
|||||||
header->size = size;
|
header->size = size;
|
||||||
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
|
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
|
||||||
header->line_num = line;
|
header->line_num = line;
|
||||||
ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
|
ofs = strlen(file) + 1 - MEM_DEBUG_FILE_LEN;
|
||||||
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
|
strcpy(header->file_name, file + (ofs > 0 ? ofs : 0));
|
||||||
header->file_name[MEM_DEBUG_FILE_LEN] = 0;
|
|
||||||
WAIT_SEM(&mem_sem);
|
WAIT_SEM(&mem_sem);
|
||||||
header->next = mem_debug_chain;
|
header->next = mem_debug_chain;
|
||||||
header->prev = NULL;
|
header->prev = NULL;
|
||||||
|
|||||||
5
tcc.c
5
tcc.c
@ -323,13 +323,12 @@ redo:
|
|||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
print_search_dirs(s);
|
print_search_dirs(s);
|
||||||
}
|
}
|
||||||
if (opt < 0) err:
|
|
||||||
ret = 1, opt = -1;
|
|
||||||
if (opt) {
|
if (opt) {
|
||||||
|
if (opt < 0) err:
|
||||||
|
ret = 1;
|
||||||
tcc_delete(s);
|
tcc_delete(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->nb_files == 0) {
|
if (s->nb_files == 0) {
|
||||||
tcc_error_noabort("no input files");
|
tcc_error_noabort("no input files");
|
||||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
|
|||||||
8
tcc.h
8
tcc.h
@ -95,13 +95,13 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
#ifdef __clang__ // clang -fsanitize compains about: NULL+value
|
#ifdef __clang__ // clang -fsanitize compains about: NULL+value
|
||||||
#define offsetof(type, field) __builtin_offsetof(type, field)
|
#define offsetof(type, field) __builtin_offsetof(type, field)
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
#ifndef offsetof
|
|
||||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef countof
|
#ifndef countof
|
||||||
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
||||||
@ -1074,7 +1074,7 @@ struct filespec {
|
|||||||
|
|
||||||
#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
|
#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
|
||||||
#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
|
#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
|
||||||
#define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
|
#define VT_ENUM_VAL (4 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
|
||||||
|
|
||||||
#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
|
#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
|
||||||
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
||||||
|
|||||||
93
tccdbg.c
93
tccdbg.c
@ -1675,16 +1675,20 @@ static void tcc_debug_check_forw(TCCState *s1, Sym *t, int debug_type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stabs_struct_complete(TCCState *s1, CType *t);
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_fix_forw(TCCState *s1, CType *t)
|
ST_FUNC void tcc_debug_fix_forw(TCCState *s1, CType *t)
|
||||||
{
|
{
|
||||||
if (!(s1->do_debug & 2))
|
if (!(s1->do_debug & 2))
|
||||||
return;
|
return;
|
||||||
|
if (0 == s1->dwarf) {
|
||||||
|
stabs_struct_complete(s1, t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1) {
|
if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1) {
|
||||||
int i, j, debug_type, g = check_global(t->ref);
|
int i, j, debug_type, g = check_global(t->ref);
|
||||||
int *n_forw_hash;
|
int *n_forw_hash;
|
||||||
struct _debug_forw_hash **forw_hash;
|
struct _debug_forw_hash **forw_hash;
|
||||||
|
|
||||||
forw_hash = g ? &debug_forw_hash_global : &debug_forw_hash_local;
|
forw_hash = g ? &debug_forw_hash_global : &debug_forw_hash_local;
|
||||||
n_forw_hash = g ? &n_debug_forw_hash_global : &n_debug_forw_hash_local;
|
n_forw_hash = g ? &n_debug_forw_hash_global : &n_debug_forw_hash_local;
|
||||||
for (i = 0; i < *n_forw_hash; i++)
|
for (i = 0; i < *n_forw_hash; i++)
|
||||||
@ -1722,14 +1726,46 @@ static int tcc_debug_add(TCCState *s1, Sym *t, int dwarf)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STRUCT_NODEBUG(s) \
|
static int STRUCT_NODEBUG(Sym *s)
|
||||||
(s->a.nodebug || \
|
{
|
||||||
((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && \
|
return
|
||||||
((s->type.t & VT_BTYPE) == VT_BYTE || \
|
(s->a.nodebug ||
|
||||||
(s->type.t & VT_BTYPE) == VT_BOOL || \
|
((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM &&
|
||||||
(s->type.t & VT_BTYPE) == VT_SHORT || \
|
((s->type.t & VT_BTYPE) == VT_BYTE ||
|
||||||
(s->type.t & VT_BTYPE) == VT_INT || \
|
(s->type.t & VT_BTYPE) == VT_BOOL ||
|
||||||
(s->type.t & VT_BTYPE) == VT_LLONG)))
|
(s->type.t & VT_BTYPE) == VT_SHORT ||
|
||||||
|
(s->type.t & VT_BTYPE) == VT_INT ||
|
||||||
|
(s->type.t & VT_BTYPE) == VT_LLONG)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stabs_struct_find(TCCState *s1, Sym *t, int *p_id)
|
||||||
|
{
|
||||||
|
/* A struct/enum has a ref to its type but that type has no ref.
|
||||||
|
So we can (ab)use it for some info. Here:
|
||||||
|
s->c : stabs type id
|
||||||
|
s->r : already defined in stabs */
|
||||||
|
Sym *s = t->type.ref;
|
||||||
|
/*
|
||||||
|
if (s && s->v != (SYM_FIELD|0x00DEBBED)) {
|
||||||
|
tcc_error_noabort("tccdbg: internal error: %s", get_tok_str(t->v, 0));
|
||||||
|
if (p_id)
|
||||||
|
*p_id = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (NULL == p_id)
|
||||||
|
return s && !s->r && t->c >= 0;
|
||||||
|
if (NULL == s) {
|
||||||
|
/* just use global_stack always */
|
||||||
|
s = sym_push2(&global_stack, SYM_FIELD|0x00DEBBED, 0, ++debug_next_type);
|
||||||
|
t->type.ref = s;
|
||||||
|
}
|
||||||
|
*p_id = s->c;
|
||||||
|
if (s->r || t->c < 0) /* already defined or still incomplete */
|
||||||
|
return 0;
|
||||||
|
s->r = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
||||||
{
|
{
|
||||||
@ -1750,9 +1786,7 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
|||||||
}
|
}
|
||||||
if ((type & VT_BTYPE) == VT_STRUCT) {
|
if ((type & VT_BTYPE) == VT_STRUCT) {
|
||||||
t = t->type.ref;
|
t = t->type.ref;
|
||||||
debug_type = tcc_debug_find(s1, t, 0);
|
if (stabs_struct_find(s1, t, &debug_type)) {
|
||||||
if (debug_type == -1) {
|
|
||||||
debug_type = tcc_debug_add(s1, t, 0);
|
|
||||||
cstr_new (&str);
|
cstr_new (&str);
|
||||||
cstr_printf (&str, "%s:T%d=%c%d",
|
cstr_printf (&str, "%s:T%d=%c%d",
|
||||||
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
||||||
@ -1760,15 +1794,16 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
|||||||
debug_type,
|
debug_type,
|
||||||
IS_UNION (t->type.t) ? 'u' : 's',
|
IS_UNION (t->type.t) ? 'u' : 's',
|
||||||
t->c);
|
t->c);
|
||||||
|
|
||||||
while (t->next) {
|
while (t->next) {
|
||||||
int pos, size, align;
|
int pos, size, align;
|
||||||
|
|
||||||
t = t->next;
|
t = t->next;
|
||||||
if (STRUCT_NODEBUG(t))
|
if (STRUCT_NODEBUG(t))
|
||||||
continue;
|
continue;
|
||||||
tcc_debug_check_forw(s1, t, -1);
|
|
||||||
cstr_printf (&str, "%s:",
|
cstr_printf (&str, "%s:",
|
||||||
get_tok_str(t->v, NULL));
|
(t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
||||||
|
? "" : get_tok_str(t->v, NULL)
|
||||||
|
);
|
||||||
tcc_get_debug_info (s1, t, &str);
|
tcc_get_debug_info (s1, t, &str);
|
||||||
if (t->type.t & VT_BITFIELD) {
|
if (t->type.t & VT_BITFIELD) {
|
||||||
pos = t->c * 8 + BIT_POS(t->type.t);
|
pos = t->c * 8 + BIT_POS(t->type.t);
|
||||||
@ -1787,10 +1822,7 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
|||||||
}
|
}
|
||||||
else if (IS_ENUM(type)) {
|
else if (IS_ENUM(type)) {
|
||||||
Sym *e = t = t->type.ref;
|
Sym *e = t = t->type.ref;
|
||||||
|
if (stabs_struct_find(s1, t, &debug_type)) {
|
||||||
debug_type = tcc_debug_find(s1, t, 0);
|
|
||||||
if (debug_type == -1) {
|
|
||||||
debug_type = tcc_debug_add(s1, t, 0);
|
|
||||||
cstr_new (&str);
|
cstr_new (&str);
|
||||||
cstr_printf (&str, "%s:T%d=e",
|
cstr_printf (&str, "%s:T%d=e",
|
||||||
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
||||||
@ -1817,6 +1849,10 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
|||||||
if (debug_type > N_DEFAULT_DEBUG)
|
if (debug_type > N_DEFAULT_DEBUG)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL == result) /* from stabs_struct_complete() */
|
||||||
|
return;
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
cstr_printf (result, "%d=", ++debug_next_type);
|
cstr_printf (result, "%d=", ++debug_next_type);
|
||||||
t = s;
|
t = s;
|
||||||
@ -1836,12 +1872,19 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
tcc_debug_check_forw(s1, t, -1);
|
|
||||||
t = t->type.ref;
|
t = t->type.ref;
|
||||||
}
|
}
|
||||||
cstr_printf (result, "%d", debug_type);
|
cstr_printf (result, "%d", debug_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stabs_struct_complete(TCCState *s1, CType *t)
|
||||||
|
{
|
||||||
|
if (stabs_struct_find(s1, t->ref, NULL)) {
|
||||||
|
Sym s = {0}; s.type = *t;
|
||||||
|
tcc_get_debug_info(s1, &s, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
@ -1993,7 +2036,7 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
|||||||
dwarf_data1(dwarf_info_section, DWARF_ABBREV_BASE_TYPE);
|
dwarf_data1(dwarf_info_section, DWARF_ABBREV_BASE_TYPE);
|
||||||
dwarf_uleb128(dwarf_info_section, default_debug[i - 1].size);
|
dwarf_uleb128(dwarf_info_section, default_debug[i - 1].size);
|
||||||
dwarf_data1(dwarf_info_section, default_debug[i - 1].encoding);
|
dwarf_data1(dwarf_info_section, default_debug[i - 1].encoding);
|
||||||
strncpy(name, default_debug[i - 1].name, sizeof(name) -1);
|
pstrcpy(name, sizeof name, default_debug[i - 1].name);
|
||||||
*strchr(name, ':') = 0;
|
*strchr(name, ':') = 0;
|
||||||
dwarf_strp(dwarf_info_section, name);
|
dwarf_strp(dwarf_info_section, name);
|
||||||
dwarf_info.base_type_used[i - 1] = debug_type;
|
dwarf_info.base_type_used[i - 1] = debug_type;
|
||||||
@ -2404,7 +2447,6 @@ ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bi
|
|||||||
sym_bind == STB_GLOBAL ? 'G' : func_ind != -1 ? 'V' : 'S'
|
sym_bind == STB_GLOBAL ? 'G' : func_ind != -1 ? 'V' : 'S'
|
||||||
);
|
);
|
||||||
tcc_get_debug_info(s1, sym, &str);
|
tcc_get_debug_info(s1, sym, &str);
|
||||||
tcc_debug_check_forw(s1, sym, -1);
|
|
||||||
if (sym_bind == STB_GLOBAL)
|
if (sym_bind == STB_GLOBAL)
|
||||||
tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0, 0);
|
tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0, 0);
|
||||||
else
|
else
|
||||||
@ -2437,11 +2479,8 @@ ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym)
|
|||||||
{
|
{
|
||||||
CString str;
|
CString str;
|
||||||
cstr_new (&str);
|
cstr_new (&str);
|
||||||
cstr_printf (&str, "%s:t",
|
cstr_printf (&str, "%s:t", get_tok_str(sym->v, NULL));
|
||||||
(sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
|
||||||
? "" : get_tok_str(sym->v, NULL));
|
|
||||||
tcc_get_debug_info(s1, sym, &str);
|
tcc_get_debug_info(s1, sym, &str);
|
||||||
tcc_debug_check_forw(s1, sym, -1);
|
|
||||||
tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
|
tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
|
||||||
cstr_free (&str);
|
cstr_free (&str);
|
||||||
}
|
}
|
||||||
|
|||||||
22
tccgen.c
22
tccgen.c
@ -1294,16 +1294,21 @@ static Sym *sym_copy(Sym *s0, Sym **ps)
|
|||||||
Sym *s;
|
Sym *s;
|
||||||
s = sym_malloc(), *s = *s0;
|
s = sym_malloc(), *s = *s0;
|
||||||
s->prev = *ps, *ps = s;
|
s->prev = *ps, *ps = s;
|
||||||
if ((s->v & ~SYM_STRUCT) < SYM_FIRST_ANOM)
|
if ((s->v & ~SYM_STRUCT) < SYM_FIRST_ANOM && ps == &local_stack)
|
||||||
sym_link(s, 1);
|
sym_link(s, 1);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy s->type.ref to stack 'ps' for VT_FUNC and VT_PTR */
|
/* Symbol 's' was locally declared 'extern' (or as function), and
|
||||||
|
is on global_stack. Now must copy its 'ref' to global_stack too */
|
||||||
static void sym_copy_ref(Sym *s, Sym **ps)
|
static void sym_copy_ref(Sym *s, Sym **ps)
|
||||||
{
|
{
|
||||||
int bt = s->type.t & VT_BTYPE;
|
int bt = s->type.t & VT_BTYPE;
|
||||||
if (bt == VT_FUNC || bt == VT_PTR || (bt == VT_STRUCT && s->sym_scope)) {
|
if (bt == VT_PTR
|
||||||
|
|| bt == VT_FUNC
|
||||||
|
|| ((bt == VT_STRUCT || IS_ENUM(s->type.t))
|
||||||
|
&& s->type.ref
|
||||||
|
&& s->type.ref->sym_scope)) {
|
||||||
Sym **sp = &s->type.ref;
|
Sym **sp = &s->type.ref;
|
||||||
for (s = *sp, *sp = NULL; s; s = s->next) {
|
for (s = *sp, *sp = NULL; s; s = s->next) {
|
||||||
Sym *s2 = sym_copy(s, ps);
|
Sym *s2 = sym_copy(s, ps);
|
||||||
@ -5962,13 +5967,10 @@ ST_FUNC void unary(void)
|
|||||||
learn = 1;
|
learn = 1;
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
AttributeDef ad_tmp;
|
int v;
|
||||||
int itmp;
|
parse_btype(&type, &ad, 0);
|
||||||
CType cur_type;
|
type_decl(&type, &ad, &v, TYPE_ABSTRACT);
|
||||||
|
if (compare_types(&controlling_type, &type, 0)) {
|
||||||
parse_btype(&cur_type, &ad_tmp, 0);
|
|
||||||
type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT);
|
|
||||||
if (compare_types(&controlling_type, &cur_type, 0)) {
|
|
||||||
if (has_match) {
|
if (has_match) {
|
||||||
tcc_error("type match twice");
|
tcc_error("type match twice");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
#include <stdio.h>
|
int printf(const char*, ...);
|
||||||
|
|
||||||
|
#define myassert(x) \
|
||||||
|
printf("%s:%d: %s : \"%s\"\n", __FILE__,__LINE__,(x)?"ok":"error",#x)
|
||||||
|
|
||||||
enum{ in = 0};
|
enum{ in = 0};
|
||||||
#define myassert(X) do{ if(!X) printf("%d: assertion failed\n", __LINE__); }while(0)
|
|
||||||
int main(){
|
int main_1(){
|
||||||
{
|
{
|
||||||
myassert(!in);
|
myassert(!in);
|
||||||
if(sizeof(enum{in=1})) myassert(in);
|
if(sizeof(enum{in=1})) myassert(in);
|
||||||
@ -38,6 +42,45 @@ int main(){
|
|||||||
for(;sizeof(enum{in=1});){ myassert(in); break; }
|
for(;sizeof(enum{in=1});){ myassert(in); break; }
|
||||||
myassert(!in); //OK
|
myassert(!in); //OK
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
int main_2()
|
||||||
|
{
|
||||||
|
char c = 'a';
|
||||||
|
void func1(char c); /* param 'c' must not shadow local 'c' */
|
||||||
|
func1(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void func1(char c)
|
||||||
|
{
|
||||||
|
myassert(c == 'a');
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st { int a; };
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
int main_3()
|
||||||
|
{
|
||||||
|
struct st func(void);
|
||||||
|
struct st st = func(); /* not an 'incompatible redefinition' */
|
||||||
|
myassert(st.a == 10);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st func(void)
|
||||||
|
{
|
||||||
|
struct st st = { 10 };
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------- */
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
main_1();
|
||||||
|
main_2();
|
||||||
|
main_3();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
129_scopes.c:10: ok : "!in"
|
||||||
|
129_scopes.c:11: ok : "in"
|
||||||
|
129_scopes.c:12: ok : "!in"
|
||||||
|
129_scopes.c:15: ok : "!in"
|
||||||
|
129_scopes.c:16: ok : "in"
|
||||||
|
129_scopes.c:17: ok : "!in"
|
||||||
|
129_scopes.c:20: ok : "!in"
|
||||||
|
129_scopes.c:21: ok : "in"
|
||||||
|
129_scopes.c:22: ok : "!in"
|
||||||
|
129_scopes.c:25: ok : "!in"
|
||||||
|
129_scopes.c:26: ok : "!in"
|
||||||
|
129_scopes.c:27: ok : "!in"
|
||||||
|
129_scopes.c:31: ok : "!in"
|
||||||
|
129_scopes.c:32: ok : "in"
|
||||||
|
129_scopes.c:33: ok : "!in"
|
||||||
|
129_scopes.c:36: ok : "!in"
|
||||||
|
129_scopes.c:37: ok : "in"
|
||||||
|
129_scopes.c:38: ok : "!in"
|
||||||
|
129_scopes.c:41: ok : "!in"
|
||||||
|
129_scopes.c:42: ok : "in"
|
||||||
|
129_scopes.c:43: ok : "!in"
|
||||||
|
129_scopes.c:59: ok : "c == 'a'"
|
||||||
|
129_scopes.c:69: ok : "st.a == 10"
|
||||||
Loading…
Reference in New Issue
Block a user