diff --git a/arm-link.c b/arm-link.c index 16e1549d..455b7363 100644 --- a/arm-link.c +++ b/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: { 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 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); #endif - write32le(ptr, read32le(ptr) & 0xff000000); - if (x & 0x800000) - x -= 0x1000000; - x = (unsigned) x << 2; + code &= 0xff000000; + x <<= 2; + if (x & 0x2000000) + x -= 0x4000000; blx_avail = (CONFIG_TCC_CPUVER >= 5); 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)); x += val - addr; #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 */ if (is_thumb) { x |= h << 24; - write32le(ptr, 0xfa << 24); /* bl -> blx */ + code = 0xfa000000; /* bl -> blx */ } - write32le(ptr, read32le(ptr) | x); + write32le(ptr, code | x); } return; /* Since these relocations only concern Thumb-2 and blx instruction was diff --git a/libtcc.c b/libtcc.c index b9bd9f57..6cd7baee 100644 --- a/libtcc.c +++ b/libtcc.c @@ -326,7 +326,7 @@ struct mem_debug_header { struct mem_debug_header *prev; struct mem_debug_header *next; int line_num; - char file_name[MEM_DEBUG_FILE_LEN + 1]; + char file_name[MEM_DEBUG_FILE_LEN]; unsigned magic2; 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; write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3); header->line_num = line; - ofs = strlen(file) - MEM_DEBUG_FILE_LEN; - strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); - header->file_name[MEM_DEBUG_FILE_LEN] = 0; + ofs = strlen(file) + 1 - MEM_DEBUG_FILE_LEN; + strcpy(header->file_name, file + (ofs > 0 ? ofs : 0)); WAIT_SEM(&mem_sem); header->next = mem_debug_chain; header->prev = NULL; diff --git a/tcc.c b/tcc.c index 7b19b4ee..b28c0b32 100644 --- a/tcc.c +++ b/tcc.c @@ -323,13 +323,12 @@ redo: tcc_set_output_type(s, TCC_OUTPUT_MEMORY); print_search_dirs(s); } - if (opt < 0) err: - ret = 1, opt = -1; if (opt) { + if (opt < 0) err: + ret = 1; tcc_delete(s); return ret; } - if (s->nb_files == 0) { tcc_error_noabort("no input files"); } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { diff --git a/tcc.h b/tcc.h index 995bd370..b3c4525e 100644 --- a/tcc.h +++ b/tcc.h @@ -95,13 +95,13 @@ extern long double strtold (const char *__nptr, char **__endptr); # define O_BINARY 0 #endif +#ifndef offsetof #ifdef __clang__ // clang -fsanitize compains about: NULL+value #define offsetof(type, field) __builtin_offsetof(type, field) -#endif - -#ifndef offsetof +#else #define offsetof(type, field) ((size_t) &((type *)0)->field) #endif +#endif #ifndef countof #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_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_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL) diff --git a/tccdbg.c b/tccdbg.c index fda97865..e50f6cc1 100644 --- a/tccdbg.c +++ b/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) { if (!(s1->do_debug & 2)) return; - + if (0 == s1->dwarf) { + stabs_struct_complete(s1, t); + return; + } if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1) { int i, j, debug_type, g = check_global(t->ref); int *n_forw_hash; struct _debug_forw_hash **forw_hash; - 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; 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; } -#define STRUCT_NODEBUG(s) \ - (s->a.nodebug || \ - ((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && \ - ((s->type.t & VT_BTYPE) == VT_BYTE || \ - (s->type.t & VT_BTYPE) == VT_BOOL || \ - (s->type.t & VT_BTYPE) == VT_SHORT || \ - (s->type.t & VT_BTYPE) == VT_INT || \ - (s->type.t & VT_BTYPE) == VT_LLONG))) +static int STRUCT_NODEBUG(Sym *s) +{ + return + (s->a.nodebug || + ((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && + ((s->type.t & VT_BTYPE) == VT_BYTE || + (s->type.t & VT_BTYPE) == VT_BOOL || + (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) { @@ -1750,9 +1786,7 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result) } if ((type & VT_BTYPE) == VT_STRUCT) { t = t->type.ref; - debug_type = tcc_debug_find(s1, t, 0); - if (debug_type == -1) { - debug_type = tcc_debug_add(s1, t, 0); + if (stabs_struct_find(s1, t, &debug_type)) { cstr_new (&str); cstr_printf (&str, "%s:T%d=%c%d", (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, IS_UNION (t->type.t) ? 'u' : 's', t->c); + while (t->next) { int pos, size, align; - t = t->next; if (STRUCT_NODEBUG(t)) continue; - tcc_debug_check_forw(s1, t, -1); 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); if (t->type.t & VT_BITFIELD) { 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)) { Sym *e = t = t->type.ref; - - debug_type = tcc_debug_find(s1, t, 0); - if (debug_type == -1) { - debug_type = tcc_debug_add(s1, t, 0); + if (stabs_struct_find(s1, t, &debug_type)) { cstr_new (&str); cstr_printf (&str, "%s:T%d=e", (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) return; } + + if (NULL == result) /* from stabs_struct_complete() */ + return; + if (n > 0) cstr_printf (result, "%d=", ++debug_next_type); t = s; @@ -1836,12 +1872,19 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result) } else break; - tcc_debug_check_forw(s1, t, -1); t = t->type.ref; } 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) { 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_uleb128(dwarf_info_section, default_debug[i - 1].size); 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; dwarf_strp(dwarf_info_section, name); 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' ); tcc_get_debug_info(s1, sym, &str); - tcc_debug_check_forw(s1, sym, -1); if (sym_bind == STB_GLOBAL) tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0, 0); else @@ -2437,11 +2479,8 @@ ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym) { CString str; cstr_new (&str); - cstr_printf (&str, "%s:t", - (sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM - ? "" : get_tok_str(sym->v, NULL)); + cstr_printf (&str, "%s:t", get_tok_str(sym->v, NULL)); 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); cstr_free (&str); } diff --git a/tccgen.c b/tccgen.c index 65122267..4cecf283 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1294,16 +1294,21 @@ static Sym *sym_copy(Sym *s0, Sym **ps) Sym *s; s = sym_malloc(), *s = *s0; 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); 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) { 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; for (s = *sp, *sp = NULL; s; s = s->next) { Sym *s2 = sym_copy(s, ps); @@ -5962,13 +5967,10 @@ ST_FUNC void unary(void) learn = 1; next(); } else { - AttributeDef ad_tmp; - int itmp; - CType cur_type; - - parse_btype(&cur_type, &ad_tmp, 0); - type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); - if (compare_types(&controlling_type, &cur_type, 0)) { + int v; + parse_btype(&type, &ad, 0); + type_decl(&type, &ad, &v, TYPE_ABSTRACT); + if (compare_types(&controlling_type, &type, 0)) { if (has_match) { tcc_error("type match twice"); } diff --git a/tests/tests2/129_scopes.c b/tests/tests2/129_scopes.c index b63b6822..08c8b316 100644 --- a/tests/tests2/129_scopes.c +++ b/tests/tests2/129_scopes.c @@ -1,7 +1,11 @@ -#include +int printf(const char*, ...); + +#define myassert(x) \ + printf("%s:%d: %s : \"%s\"\n", __FILE__,__LINE__,(x)?"ok":"error",#x) + enum{ in = 0}; -#define myassert(X) do{ if(!X) printf("%d: assertion failed\n", __LINE__); }while(0) -int main(){ + +int main_1(){ { myassert(!in); if(sizeof(enum{in=1})) myassert(in); @@ -38,6 +42,45 @@ int main(){ for(;sizeof(enum{in=1});){ myassert(in); break; } 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; +} diff --git a/tests/tests2/129_scopes.expect b/tests/tests2/129_scopes.expect index e69de29b..0e90240c 100644 --- a/tests/tests2/129_scopes.expect +++ b/tests/tests2/129_scopes.expect @@ -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"