From 2bd0daabbe1fc40e65e4a4631e68f5ca093ea1fb Mon Sep 17 00:00:00 2001 From: grischka Date: Mon, 6 Jan 2014 19:56:26 +0100 Subject: misc. fixes - tccgen: error out for cast to void, as in void foo(void) { return 1; } This avoids an assertion failure in x86_64-gen.c, also. also fix tests2/03_struct.c accordingly - Error: "memory full" - be more specific - Makefiles: remove circular dependencies, lookup tcctest.c from VPATH - tcc.h: cleanup lib, include, crt and libgcc search paths" avoid duplication or trailing slashes with no CONFIG_MULTIARCHDIR (as from 9382d6f1a0e2d0104a82ed805207d9e742c6b068) - tcc.h: remove ";{B}" from PE search path in ce5e12c2f950052d8109b6b7a56d900547705c08 James Lyon wrote: "... I'm not sure this is the right way to fix this problem." And the answer is: No, please. (copying libtcc1.a for tests instead) - win32/build_tcc.bat: do not move away a versioned file --- tccpp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index aeaf6be..e1ccded 100644 --- a/tccpp.c +++ b/tccpp.c @@ -197,7 +197,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) int i; if (tok_ident >= SYM_FIRST_ANOM) - tcc_error("memory full"); + tcc_error("memory full (symbols)"); /* expand token table if needed */ i = tok_ident - TOK_IDENT; @@ -1528,7 +1528,7 @@ include_done: c = (define_find(tok) != 0) ^ c; do_if: if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) - tcc_error("memory full"); + tcc_error("memory full (ifdef)"); *s1->ifdef_stack_ptr++ = c; goto test_skip; case TOK_ELSE: -- cgit v1.3.1 From fdb3b10d0693cf33ce5a0acf17f0f323d79ee5f1 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 8 Mar 2014 18:36:02 +0800 Subject: Fix various errors uncovered by static analysis Reported-by: Carlos Montiers --- c67-gen.c | 2 -- tccgen.c | 1 - tccpp.c | 2 +- x86_64-gen.c | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) (limited to 'tccpp.c') diff --git a/c67-gen.c b/c67-gen.c index f2baea5..6d9068a 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1901,8 +1901,6 @@ void gfunc_call(int nb_args) for (i = 0; i < nb_args; i++) { if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { ALWAYS_ASSERT(FALSE); - } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { - ALWAYS_ASSERT(FALSE); } else { /* simple type (currently always same size) */ /* XXX: implicit cast ? */ diff --git a/tccgen.c b/tccgen.c index 2f5b366..d8e4614 100644 --- a/tccgen.c +++ b/tccgen.c @@ -162,7 +162,6 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } - s = *ps; s = sym_malloc(); s->asm_label = NULL; s->v = v; diff --git a/tccpp.c b/tccpp.c index e1ccded..b12b120 100644 --- a/tccpp.c +++ b/tccpp.c @@ -276,7 +276,7 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) #ifdef _WIN32 sprintf(p, "%u", (unsigned)cv->ull); #else - sprintf(p, "%Lu", cv->ull); + sprintf(p, "%llu", cv->ull); #endif break; case TOK_LCHAR: diff --git a/x86_64-gen.c b/x86_64-gen.c index 407bd96..fc4178e 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -501,7 +501,7 @@ void load(int r, SValue *sv) o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8); } } else if (r == TREG_ST0) { - assert((v >= TREG_XMM0) || (v <= TREG_XMM7)); + assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); /* gen_cvt_ftof(VT_LDOUBLE); */ /* movsd %xmmN,-0x10(%rsp) */ o(0x110ff2); -- cgit v1.3.1 From 62d1da1b3eb91b405a633aa4e4d841d8a7a0da3a Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sun, 9 Mar 2014 22:52:31 +0800 Subject: Fix warning of clang --- tccelf.c | 40 ++++++++++++++++++++-------------------- tccpp.c | 4 ++-- tccrun.c | 4 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'tccpp.c') diff --git a/tccelf.c b/tccelf.c index 321ec2e..424db69 100644 --- a/tccelf.c +++ b/tccelf.c @@ -56,7 +56,7 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) { ElfW(Sym) *sym; int *ptr, *hash, nb_syms, sym_index, h; - char *strtab; + unsigned char *strtab; strtab = s->link->data; nb_syms = s->data_offset / sizeof(ElfW(Sym)); @@ -115,7 +115,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, if (ELFW(ST_BIND)(info) != STB_LOCAL) { /* add another hashing entry */ nbuckets = base[0]; - h = elf_hash(name) % nbuckets; + h = elf_hash((unsigned char *) name) % nbuckets; *ptr = base[2 + h]; base[2 + h] = sym_index; base[1]++; @@ -145,11 +145,11 @@ ST_FUNC int find_elf_sym(Section *s, const char *name) if (!hs) return 0; nbuckets = ((int *)hs->data)[0]; - h = elf_hash(name) % nbuckets; + h = elf_hash((unsigned char *) name) % nbuckets; sym_index = ((int *)hs->data)[2 + h]; while (sym_index != 0) { sym = &((ElfW(Sym) *)s->data)[sym_index]; - name1 = s->link->data + sym->st_name; + name1 = (char *) s->link->data + sym->st_name; if (!strcmp(name, name1)) return sym_index; sym_index = ((int *)hs->data)[2 + nbuckets + sym_index]; @@ -429,12 +429,12 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { sh_num = sym->st_shndx; if (sh_num == SHN_UNDEF) { - name = strtab_section->data + sym->st_name; + name = (char *) strtab_section->data + sym->st_name; /* Use ld.so to resolve symbol for us (for tcc -run) */ if (do_resolve) { #if defined TCC_IS_NATIVE && !defined _WIN32 void *addr; - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; addr = resolve_sym(s1, name); if (addr) { sym->st_value = (addr_t)addr; @@ -1026,7 +1026,7 @@ static void put_got_entry(TCCState *s1, if (s1->dynsym) { sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; offset = sym->st_value; #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) if (reloc_type == @@ -1198,7 +1198,7 @@ ST_FUNC void build_got_entries(TCCState *s1) char *name, buf[1024]; Section *text_section; - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; text_section = s1->sections[sym->st_shndx]; /* Modify reloc to target a thumb stub to switch to ARM */ snprintf(buf, sizeof(buf), "%s_from_thumb", name); @@ -1566,7 +1566,7 @@ static void bind_exe_dynsyms(TCCState *s1) - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */ for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { if (sym->st_shndx == SHN_UNDEF) { - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; sym_index = find_elf_sym(s1->dynsymtab_section, name); if (sym_index) { esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index]; @@ -1596,7 +1596,7 @@ static void bind_exe_dynsyms(TCCState *s1) for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) { if ((dynsym->st_value == esym->st_value) && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) { - char *dynname = s1->dynsymtab_section->link->data + char *dynname = (char *) s1->dynsymtab_section->link->data + dynsym->st_name; put_elf_sym(s1->dynsym, offset, dynsym->st_size, dynsym->st_info, 0, @@ -1621,7 +1621,7 @@ static void bind_exe_dynsyms(TCCState *s1) } } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { /* if -rdynamic option, then export all non local symbols */ - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info, 0, sym->st_shndx, name); } @@ -1640,7 +1640,7 @@ static void bind_libs_dynsyms(TCCState *s1) corresponding symbol */ for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) { if (esym->st_shndx == SHN_UNDEF) { - name = s1->dynsymtab_section->link->data + esym->st_name; + name = (char *) s1->dynsymtab_section->link->data + esym->st_name; sym_index = find_elf_sym(symtab_section, name); if (sym_index) { /* XXX: avoid adding a symbol if already present because of @@ -1682,7 +1682,7 @@ static void export_global_syms(TCCState *s1) } else #endif { - name = symtab_section->link->data + sym->st_name; + name = (char *) symtab_section->link->data + sym->st_name; dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info, 0, sym->st_shndx, name); index = sym - (ElfW(Sym) *) symtab_section->data; @@ -2527,7 +2527,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, if (i == ehdr.e_shstrndx) continue; sh = &shdr[i]; - sh_name = strsec + sh->sh_name; + sh_name = (char *) strsec + sh->sh_name; /* ignore sections types we do not handle */ if (sh->sh_type != SHT_PROGBITS && sh->sh_type != SHT_RELX && @@ -2648,7 +2648,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, already defined symbol. It is very important to get correct relocations */ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { - name = strtab + sym->st_name; + name = (char *) strtab + sym->st_name; sym_index = find_elf_sym(symtab_section, name); if (sym_index) old_to_new_syms[i] = sym_index; @@ -2664,7 +2664,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, sym->st_value += sm->offset; } /* add symbol */ - name = strtab + sym->st_name; + name = (char *) strtab + sym->st_name; sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx, name); @@ -2765,7 +2765,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size) goto fail; nsyms = get_be32(data); ar_index = data + 4; - ar_names = ar_index + nsyms * 4; + ar_names = (char *) ar_index + nsyms * 4; do { bound = 0; @@ -2898,7 +2898,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { if (dt->d_tag == DT_SONAME) { - soname = dynstr + dt->d_un.d_val; + soname = (char *) dynstr + dt->d_un.d_val; } } @@ -2925,7 +2925,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) sym_bind = ELFW(ST_BIND)(sym->st_info); if (sym_bind == STB_LOCAL) continue; - name = dynstr + sym->st_name; + name = (char *) dynstr + sym->st_name; add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx, name); } @@ -2934,7 +2934,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { switch(dt->d_tag) { case DT_NEEDED: - name = dynstr + dt->d_un.d_val; + name = (char *) dynstr + dt->d_un.d_val; for(j = 0; j < s1->nb_loaded_dlls; j++) { dllref = s1->loaded_dlls[j]; if (!strcmp(name, dllref->name)) diff --git a/tccpp.c b/tccpp.c index b12b120..cf1fc65 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1247,7 +1247,7 @@ static inline int hash_cached_include(const char *filename) unsigned int h; h = TOK_HASH_INIT; - s = filename; + s = (unsigned char *) filename; while (*s) { h = TOK_HASH_FUNC(h, *s); s++; @@ -2222,7 +2222,7 @@ maybe_newline: goto token_found; pts = &(ts->hash_next); } - ts = tok_alloc_new(pts, p1, len); + ts = tok_alloc_new(pts, (char *) p1, len); token_found: ; } else { /* slower case */ diff --git a/tccrun.c b/tccrun.c index 620be0d..bd8c33f 100644 --- a/tccrun.c +++ b/tccrun.c @@ -272,7 +272,7 @@ static addr_t rt_printline(addr_t wanted_pc, const char *msg) if (stab_section) { stab_len = stab_section->data_offset; stab_sym = (Stab_Sym *)stab_section->data; - stab_str = stabstr_section->data; + stab_str = (char *) stabstr_section->data; } func_name[0] = '\0'; @@ -365,7 +365,7 @@ no_stabs: if (wanted_pc >= sym->st_value && wanted_pc < sym->st_value + sym->st_size) { pstrcpy(last_func_name, sizeof(last_func_name), - strtab_section->data + sym->st_name); + (char *) strtab_section->data + sym->st_name); func_addr = sym->st_value; goto found; } -- cgit v1.3.1 From 4bc83ac3933efa565ae3326b55fcd711b63c073d Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 26 Mar 2014 20:14:39 +0000 Subject: After several days searching why my code refactoring to remove globals was crashing, I found the problem it was because CValue stack variables have rubish as it inital values and assigning to a member that is smaller than the big union item and trying to recover it later as a different member gives bak garbage. ST_FUNC void vset(TCCState* tcc_state, CType *type, int r, int v) { CValue cval; memset(&cval, 0, sizeof(CValue)); cval.i = v; //,<<<<<<<<<<< here is the main bug that mix with garbage vsetc(tcc_state, type, r, &cval); } /* store a value or an expression directly in global data or in local array */ static void init_putv(TCCState* tcc_state, CType *type, Section *sec, unsigned long c, int v, int expr_type) { ... case VT_PTR: if (tcc_state->tccgen_vtop->r & VT_SYM) { greloc(tcc_state, sec, tcc_state->tccgen_vtop->sym, c, R_DATA_PTR); } //<<< on the next line is where we try to get the assigned value to cvalue.i as cvalue.ull *(addr_t *)ptr |= (tcc_state->tccgen_vtop->c.ull & bit_mask) << bit_pos; break; Also this patch makes vla tests pass on linux 32 bits --- tccgen.c | 9 ++++++++- tccpp.c | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'tccpp.c') diff --git a/tccgen.c b/tccgen.c index 9c12c92..b4f97f4 100644 --- a/tccgen.c +++ b/tccgen.c @@ -329,6 +329,7 @@ static void vsetc(CType *type, int r, CValue *vc) void vpush(CType *type) { CValue cval; + memset(&cval, 0, sizeof(CValue)); vsetc(type, VT_CONST, &cval); } @@ -336,6 +337,7 @@ void vpush(CType *type) ST_FUNC void vpushi(int v) { CValue cval; + memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(&int_type, VT_CONST, &cval); } @@ -344,6 +346,7 @@ ST_FUNC void vpushi(int v) static void vpushs(long long v) { CValue cval; + memset(&cval, 0, sizeof(CValue)); if (PTR_SIZE == 4) cval.i = (int)v; else @@ -354,8 +357,9 @@ static void vpushs(long long v) /* push arbitrary 64bit constant */ void vpush64(int ty, unsigned long long v) { - CValue cval; CType ctype; + CValue cval; + memset(&cval, 0, sizeof(CValue)); ctype.t = ty; ctype.ref = NULL; cval.ull = v; @@ -372,6 +376,7 @@ static inline void vpushll(long long v) static inline void vpushsym(CType *type, Sym *sym) { CValue cval; + memset(&cval, 0, sizeof(CValue)); cval.ull = 0; vsetc(type, VT_CONST | VT_SYM, &cval); @@ -446,6 +451,7 @@ ST_FUNC void vpush_global_sym(CType *type, int v) ST_FUNC void vset(CType *type, int r, int v) { CValue cval; + memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(type, r, &cval); @@ -731,6 +737,7 @@ ST_FUNC int gv(int rc) unsigned long offset; #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) CValue check; + memset(&check, 0, sizeof(CValue)); #endif /* XXX: unify with initializers handling ? */ diff --git a/tccpp.c b/tccpp.c index cf1fc65..2609ad7 100644 --- a/tccpp.c +++ b/tccpp.c @@ -936,6 +936,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) ST_FUNC void tok_str_add_tok(TokenString *s) { CValue cval; + memset(&cval, 0, sizeof(CValue)); /* save line number info */ if (file->line_num != s->last_line_num) { @@ -999,8 +1000,9 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) static int macro_is_equal(const int *a, const int *b) { char buf[STRING_MAX_SIZE + 1]; - CValue cv; int t; + CValue cv; + memset(&cv, 0, sizeof(CValue)); while (*a && *b) { TOK_GET(&t, &a, &cv); pstrcpy(buf, sizeof buf, get_tok_str(t, &cv)); @@ -1159,6 +1161,7 @@ static void tok_print(int *str) { int t; CValue cval; + memset(&cval, 0, sizeof(CValue)); printf("<"); while (1) { @@ -2525,9 +2528,10 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) int last_tok, t, spc; const int *st; Sym *s; - CValue cval; TokenString str; CString cstr; + CValue cval; + memset(&cval, 0, sizeof(CValue)); tok_str_new(&str); last_tok = 0; @@ -2629,9 +2633,10 @@ static int macro_subst_tok(TokenString *tok_str, const int *p; TokenString str; char *cstrval; - CValue cval; CString cstr; char buf[32]; + CValue cval; + memset(&cval, 0, sizeof(CValue)); /* if symbol is a macro, prepare substitution */ /* special macros */ @@ -2806,6 +2811,7 @@ static inline int *macro_twosharps(const int *macro_str) /* we search the first '##' */ for(ptr = macro_str;;) { CValue cval; + memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); if (t == TOK_TWOSHARPS) break; @@ -2836,6 +2842,7 @@ static inline int *macro_twosharps(const int *macro_str) t = *++ptr; if (t && t != TOK_TWOSHARPS) { CValue cval; + memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); /* We concatenate the two tokens */ cstr_new(&cstr); @@ -2877,9 +2884,10 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, int *macro_str1; const int *ptr; int t, ret, spc; - CValue cval; struct macro_level ml; int force_blank; + CValue cval; + memset(&cval, 0, sizeof(CValue)); /* first scan for '##' operator handling */ ptr = macro_str; -- cgit v1.3.1 From 9a6ee577f6165dccfde424732bfc6f16f1e2811b Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 27 Mar 2014 22:59:05 +0800 Subject: Make get_tok_str support NULL as second param. As was pointed out on tinycc-devel, many uses of get_tok_str gives as second parameter the value NULL. However, that pointer was unconditionally dereferenced in get_tok_ptr. This commit explicitely add support for thas case. --- tccpp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index 2609ad7..f4b7b1a 100644 --- a/tccpp.c +++ b/tccpp.c @@ -255,9 +255,15 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) static char buf[STRING_MAX_SIZE + 1]; static CString cstr_buf; CString *cstr; + CValue cval; char *p; int i, len; + if (!cv) { + cval.ull = 0; + cv = &cval; + } + /* NOTE: to go faster, we give a fixed buffer for small strings */ cstr_reset(&cstr_buf); cstr_buf.data = buf; -- cgit v1.3.1 From 0ac8aaab1bef770929e5592d02bc06d3a529952e Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 29 Mar 2014 16:40:54 +0100 Subject: tccpp: reorder some tokens ... and make future reordering possibly easier related to 9a6ee577f6165dccfde424732bfc6f16f1e2811b --- tcc.h | 33 ++++++++++++++++++--------------- tccpp.c | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 21 deletions(-) (limited to 'tccpp.c') diff --git a/tcc.h b/tcc.h index e83e6c0..f89b146 100644 --- a/tcc.h +++ b/tcc.h @@ -783,35 +783,38 @@ struct TCCState { #define TOK_LAND 0xa0 #define TOK_LOR 0xa1 - #define TOK_DEC 0xa2 #define TOK_MID 0xa3 /* inc/dec, to void constant */ #define TOK_INC 0xa4 #define TOK_UDIV 0xb0 /* unsigned division */ #define TOK_UMOD 0xb1 /* unsigned modulo */ #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */ -#define TOK_CINT 0xb3 /* number in tokc */ -#define TOK_CCHAR 0xb4 /* char constant in tokc */ -#define TOK_STR 0xb5 /* pointer to string in tokc */ -#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */ -#define TOK_LCHAR 0xb7 -#define TOK_LSTR 0xb8 -#define TOK_CFLOAT 0xb9 /* float constant */ -#define TOK_LINENUM 0xba /* line number info */ -#define TOK_CDOUBLE 0xc0 /* double constant */ -#define TOK_CLDOUBLE 0xc1 /* long double constant */ + +/* tokens that carry values (in additional token string space / tokc) --> */ +#define TOK_CCHAR 0xb3 /* char constant in tokc */ +#define TOK_LCHAR 0xb4 +#define TOK_CINT 0xb5 /* number in tokc */ +#define TOK_CUINT 0xb6 /* unsigned int constant */ +#define TOK_CLLONG 0xb7 /* long long constant */ +#define TOK_CULLONG 0xb8 /* unsigned long long constant */ +#define TOK_STR 0xb9 /* pointer to string in tokc */ +#define TOK_LSTR 0xba +#define TOK_CFLOAT 0xbb /* float constant */ +#define TOK_CDOUBLE 0xbc /* double constant */ +#define TOK_CLDOUBLE 0xbd /* long double constant */ +#define TOK_PPNUM 0xbe /* preprocessor number */ +#define TOK_LINENUM 0xbf /* line number info */ +/* <-- */ + +#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */ #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ #define TOK_ADDC1 0xc3 /* add with carry generation */ #define TOK_ADDC2 0xc4 /* add with carry use */ #define TOK_SUBC1 0xc5 /* add with carry generation */ #define TOK_SUBC2 0xc6 /* add with carry use */ -#define TOK_CUINT 0xc8 /* unsigned int constant */ -#define TOK_CLLONG 0xc9 /* long long constant */ -#define TOK_CULLONG 0xca /* unsigned long long constant */ #define TOK_ARROW 0xcb #define TOK_DOTS 0xcc /* three dots */ #define TOK_SHR 0xcd /* unsigned shift right */ -#define TOK_PPNUM 0xce /* preprocessor number */ #define TOK_NOSUBST 0xcf /* means following token has already been pp'd */ #define TOK_SHL 0x01 /* shift left */ diff --git a/tccpp.c b/tccpp.c index f4b7b1a..b2e389b 100644 --- a/tccpp.c +++ b/tccpp.c @@ -70,8 +70,33 @@ static const char tcc_keywords[] = /* WARNING: the content of this string encodes token numbers */ static const unsigned char tok_two_chars[] = +/* outdated -- gr "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253" "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; +*/{ + '<','=', TOK_LE, + '>','=', TOK_GE, + '!','=', TOK_NE, + '&','&', TOK_LAND, + '|','|', TOK_LOR, + '+','+', TOK_INC, + '-','-', TOK_DEC, + '=','=', TOK_EQ, + '<','<', TOK_SHL, + '>','>', TOK_SHR, + '+','=', TOK_A_ADD, + '-','=', TOK_A_SUB, + '*','=', TOK_A_MUL, + '/','=', TOK_A_DIV, + '%','=', TOK_A_MOD, + '&','=', TOK_A_AND, + '^','=', TOK_A_XOR, + '|','=', TOK_A_OR, + '-','>', TOK_ARROW, + '.','.', 0xa8, // C++ token ? + '#','#', TOK_TWOSHARPS, + 0 +}; struct macro_level { struct macro_level *prev; @@ -255,21 +280,19 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) static char buf[STRING_MAX_SIZE + 1]; static CString cstr_buf; CString *cstr; - CValue cval; char *p; int i, len; - if (!cv) { - cval.ull = 0; - cv = &cval; - } - /* NOTE: to go faster, we give a fixed buffer for small strings */ cstr_reset(&cstr_buf); cstr_buf.data = buf; cstr_buf.size_allocated = sizeof(buf); p = buf; +/* just an explanation, should never happen: + if (v <= TOK_LINENUM && v >= TOK_CINT && cv == NULL) + tcc_error("internal error: get_tok_str"); */ + switch(v) { case TOK_CINT: case TOK_CUINT: @@ -317,6 +340,15 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) cstr_ccat(&cstr_buf, '\"'); cstr_ccat(&cstr_buf, '\0'); break; + + case TOK_CFLOAT: + case TOK_CDOUBLE: + case TOK_CLDOUBLE: + case TOK_LINENUM: + return NULL; /* should not happen */ + + /* above tokens have value, the ones below don't */ + case TOK_LT: v = '<'; goto addv; -- cgit v1.3.1 From a620b12dc18e7e40c7497dcfb976a5628c3e57f9 Mon Sep 17 00:00:00 2001 From: Vincent Lefevre Date: Mon, 31 Mar 2014 15:24:32 +0200 Subject: Fixed typo from commit 0ac8aaab1bef770929e5592d02bc06d3a529952e --- tccpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index b2e389b..fbf109b 100644 --- a/tccpp.c +++ b/tccpp.c @@ -83,7 +83,7 @@ static const unsigned char tok_two_chars[] = '-','-', TOK_DEC, '=','=', TOK_EQ, '<','<', TOK_SHL, - '>','>', TOK_SHR, + '>','>', TOK_SAR, '+','=', TOK_A_ADD, '-','=', TOK_A_SUB, '*','=', TOK_A_MUL, -- cgit v1.3.1 From 5879c854fb94f722a7ffdd4e895c9ce418548959 Mon Sep 17 00:00:00 2001 From: grischka Date: Fri, 4 Apr 2014 20:18:39 +0200 Subject: tccgen: x86_64: fix garbage in the SValue upper bits This was going wrong (case TOK_LAND in unary: computed labels) - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; This does the right thing and is shorter: + vpushsym(&s->type, s); Test case was: int main(int argc, char **argv) { int x; static void *label_return = &&lbl_return; printf("label_return = %p\n", label_return); goto *label_return; //<<<<< here segfault on linux X86_64 without the memset on vset printf("unreachable\n"); lbl_return: return 0; } Also:: - Rename "void* CValue.ptr" to more usable "addr_t ptr_offset" and start to use it in obvious cases. - use __attribute__ ((noreturn)) only with gnu compiler - Revert CValue memsets ("After several days searching ...") commit 4bc83ac3933efa565ae3326b55fcd711b63c073d Doesn't mean that the vsetX/vpush thingy isn't brittle and there still might be bugs as to differences in how the CValue union was set and is then interpreted later on. However the big memset hammer was just too slow (-3% overall). --- tcc.h | 76 +++++++++++++++++++++++++++++++++------------------------------- tccgen.c | 30 ++++++++----------------- tccpp.c | 16 ++++---------- 3 files changed, 52 insertions(+), 70 deletions(-) (limited to 'tccpp.c') diff --git a/tcc.h b/tcc.h index f508097..093e758 100644 --- a/tcc.h +++ b/tcc.h @@ -55,18 +55,27 @@ # ifndef CONFIG_TCC_STATIC # include # endif -#else +/* XXX: need to define this to use them in non ISOC99 context */ + extern float strtof (const char *__nptr, char **__endptr); + extern long double strtold (const char *__nptr, char **__endptr); +#else /* on _WIN32: */ # include # include # include /* open, close etc. */ # include /* getcwd */ # ifdef __GNUC__ # include -# else - typedef UINT_PTR uintptr_t; # endif # define inline __inline # define inp next_inp +# define snprintf _snprintf +# define vsnprintf _vsnprintf +# ifndef __GNUC__ +# define strtold (long double)strtod +# define strtof (float)strtod +# define strtoll _strtoi64 +# define strtoull _strtoui64 +# endif # ifdef LIBTCC_AS_DLL # define LIBTCCAPI __declspec(dllexport) # define PUB_FUNC LIBTCCAPI @@ -79,6 +88,30 @@ # define O_BINARY 0 #endif +#ifdef __GNUC__ +# define NORETURN __attribute__ ((noreturn)) +#elif defined _MSC_VER +# define NORETURN __declspec(noreturn) +#else +# define NORETURN +#endif + +#ifdef _WIN32 +# define IS_DIRSEP(c) (c == '/' || c == '\\') +# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) +# define PATHCMP stricmp +#else +# define IS_DIRSEP(c) (c == '/') +# define IS_ABSPATH(p) IS_DIRSEP(p[0]) +# define PATHCMP strcmp +#endif + +#ifdef TCC_TARGET_PE +#define PATHSEP ';' +#else +#define PATHSEP ':' +#endif + #include "elf.h" #ifdef TCC_TARGET_X86_64 # define ELFCLASSW ELFCLASS64 @@ -315,7 +348,7 @@ typedef union CValue { long long ll; unsigned long long ull; struct CString *cstr; - void *ptr; + addr_t ptr_offset; int tab[LDOUBLE_SIZE/4]; } CValue; @@ -938,37 +971,6 @@ enum tcc_token { #define TOK_UIDENT TOK_DEFINE -#ifdef _WIN32 -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#ifndef __GNUC__ -# define strtold (long double)strtod -# define strtof (float)strtod -# define strtoll _strtoi64 -# define strtoull _strtoui64 -#endif -#else -/* XXX: need to define this to use them in non ISOC99 context */ -extern float strtof (const char *__nptr, char **__endptr); -extern long double strtold (const char *__nptr, char **__endptr); -#endif - -#ifdef _WIN32 -#define IS_DIRSEP(c) (c == '/' || c == '\\') -#define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) -#define PATHCMP stricmp -#else -#define IS_DIRSEP(c) (c == '/') -#define IS_ABSPATH(p) IS_DIRSEP(p[0]) -#define PATHCMP strcmp -#endif - -#ifdef TCC_TARGET_PE -#define PATHSEP ';' -#else -#define PATHSEP ':' -#endif - /* space exlcuding newline */ static inline int is_space(int ch) { @@ -1045,7 +1047,7 @@ PUB_FUNC char *tcc_strdup(const char *str); #define strdup(s) use_tcc_strdup(s) PUB_FUNC void tcc_memstats(void); PUB_FUNC void tcc_error_noabort(const char *fmt, ...); -PUB_FUNC void tcc_error(const char *fmt, ...) __attribute__ ((noreturn)); +PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); PUB_FUNC void tcc_warning(const char *fmt, ...); /* other utilities */ @@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1); ST_FUNC void preprocess_new(void); ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC void skip(int c); -ST_FUNC void expect(const char *msg) __attribute__ ((noreturn)); +ST_FUNC NORETURN void expect(const char *msg); /* ------------ tccgen.c ------------ */ diff --git a/tccgen.c b/tccgen.c index 84188ad..b698da9 100644 --- a/tccgen.c +++ b/tccgen.c @@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc) void vpush(CType *type) { CValue cval; - memset(&cval, 0, sizeof(CValue)); vsetc(type, VT_CONST, &cval); } @@ -337,29 +336,23 @@ void vpush(CType *type) ST_FUNC void vpushi(int v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(&int_type, VT_CONST, &cval); } /* push a pointer sized constant */ -static void vpushs(long long v) +static void vpushs(addr_t v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); - if (PTR_SIZE == 4) - cval.i = (int)v; - else - cval.ull = v; + cval.ptr_offset = v; vsetc(&size_type, VT_CONST, &cval); } /* push arbitrary 64bit constant */ void vpush64(int ty, unsigned long long v) { - CType ctype; CValue cval; - memset(&cval, 0, sizeof(CValue)); + CType ctype; ctype.t = ty; ctype.ref = NULL; cval.ull = v; @@ -376,9 +369,7 @@ static inline void vpushll(long long v) static inline void vpushsym(CType *type, Sym *sym) { CValue cval; - memset(&cval, 0, sizeof(CValue)); - - cval.ull = 0; + cval.ptr_offset = 0; vsetc(type, VT_CONST | VT_SYM, &cval); vtop->sym = sym; } @@ -451,7 +442,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) ST_FUNC void vset(CType *type, int r, int v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(type, r, &cval); @@ -737,7 +727,6 @@ ST_FUNC int gv(int rc) unsigned long offset; #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) CValue check; - memset(&check, 0, sizeof(CValue)); #endif /* XXX: unify with initializers handling ? */ @@ -770,7 +759,7 @@ ST_FUNC int gv(int rc) sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); vtop->r |= VT_LVAL | VT_SYM; vtop->sym = sym; - vtop->c.ull = 0; + vtop->c.ptr_offset = 0; } #ifdef CONFIG_TCC_BCHECK if (vtop->r & VT_MUSTBOUND) @@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p) return 0; return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || - ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); } static inline int is_integer_btype(int bt) @@ -3886,8 +3875,7 @@ ST_FUNC void unary(void) mk_pointer(&s->type); s->type.t |= VT_STATIC; } - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; + vpushsym(&s->type, s); next(); break; @@ -3939,7 +3927,7 @@ ST_FUNC void unary(void) /* if forward reference, we must point to s */ if (vtop->r & VT_SYM) { vtop->sym = s; - vtop->c.ull = 0; + vtop->c.ptr_offset = 0; } break; } @@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c, if (vtop->r & VT_SYM) { greloc(sec, vtop->sym, c, R_DATA_PTR); } - *(addr_t *)ptr |= (vtop->c.ull & bit_mask) << bit_pos; + *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; break; default: if (vtop->r & VT_SYM) { diff --git a/tccpp.c b/tccpp.c index fbf109b..7144ee4 100644 --- a/tccpp.c +++ b/tccpp.c @@ -974,7 +974,6 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) ST_FUNC void tok_str_add_tok(TokenString *s) { CValue cval; - memset(&cval, 0, sizeof(CValue)); /* save line number info */ if (file->line_num != s->last_line_num) { @@ -1038,9 +1037,8 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) static int macro_is_equal(const int *a, const int *b) { char buf[STRING_MAX_SIZE + 1]; - int t; CValue cv; - memset(&cv, 0, sizeof(CValue)); + int t; while (*a && *b) { TOK_GET(&t, &a, &cv); pstrcpy(buf, sizeof buf, get_tok_str(t, &cv)); @@ -1199,7 +1197,6 @@ static void tok_print(int *str) { int t; CValue cval; - memset(&cval, 0, sizeof(CValue)); printf("<"); while (1) { @@ -2566,10 +2563,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) int last_tok, t, spc; const int *st; Sym *s; + CValue cval; TokenString str; CString cstr; - CValue cval; - memset(&cval, 0, sizeof(CValue)); tok_str_new(&str); last_tok = 0; @@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str, const int *p; TokenString str; char *cstrval; + CValue cval; CString cstr; char buf[32]; - CValue cval; - memset(&cval, 0, sizeof(CValue)); /* if symbol is a macro, prepare substitution */ /* special macros */ @@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str) /* we search the first '##' */ for(ptr = macro_str;;) { CValue cval; - memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); if (t == TOK_TWOSHARPS) break; @@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str) t = *++ptr; if (t && t != TOK_TWOSHARPS) { CValue cval; - memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); /* We concatenate the two tokens */ cstr_new(&cstr); @@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, int *macro_str1; const int *ptr; int t, ret, spc; + CValue cval; struct macro_level ml; int force_blank; - CValue cval; - memset(&cval, 0, sizeof(CValue)); /* first scan for '##' operator handling */ ptr = macro_str; -- cgit v1.3.1 From a715d7143d9d17da17e67fec6af1c01409a71a31 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 8 Apr 2014 22:19:48 +0800 Subject: Prevent ## to appear at start or end of macro --- tccpp.c | 14 +++++++++++--- tests/tests2/65_macro_concat_start.c | 2 ++ tests/tests2/65_macro_concat_start.expect | 1 + tests/tests2/66_macro_concat_end.c | 2 ++ tests/tests2/66_macro_concat_end.expect | 1 + tests/tests2/Makefile | 4 +++- 6 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 tests/tests2/65_macro_concat_start.c create mode 100644 tests/tests2/65_macro_concat_start.expect create mode 100644 tests/tests2/66_macro_concat_end.c create mode 100644 tests/tests2/66_macro_concat_end.expect (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index 7144ee4..c8beec5 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1213,9 +1213,9 @@ static void tok_print(int *str) ST_FUNC void parse_define(void) { Sym *s, *first, **ps; - int v, t, varg, is_vaargs, spc; + int v, t, varg, is_vaargs, spc, ptok, macro_list_start; TokenString str; - + v = tok; if (v < TOK_IDENT) tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc)); @@ -1254,8 +1254,13 @@ ST_FUNC void parse_define(void) tok_str_new(&str); spc = 2; /* EOF testing necessary for '-D' handling */ + ptok = 0; + macro_list_start = 1; while (tok != TOK_LINEFEED && tok != TOK_EOF) { - /* remove spaces around ## and after '#' */ + if (!macro_list_start && spc == 2 && tok == TOK_TWOSHARPS) + tcc_error("'##' invalid at start of macro"); + ptok = tok; + /* remove spaces around ## and after '#' */ if (TOK_TWOSHARPS == tok) { if (1 == spc) --str.len; @@ -1268,7 +1273,10 @@ ST_FUNC void parse_define(void) tok_str_add2(&str, tok, &tokc); skip: next_nomacro_spc(); + macro_list_start = 0; } + if (ptok == TOK_TWOSHARPS) + tcc_error("'##' invalid at end of macro"); if (spc == 1) --str.len; /* remove trailing space */ tok_str_add(&str, 0); diff --git a/tests/tests2/65_macro_concat_start.c b/tests/tests2/65_macro_concat_start.c new file mode 100644 index 0000000..d63d67a --- /dev/null +++ b/tests/tests2/65_macro_concat_start.c @@ -0,0 +1,2 @@ +#define paste(A,B) ##A B +paste(x,y) diff --git a/tests/tests2/65_macro_concat_start.expect b/tests/tests2/65_macro_concat_start.expect new file mode 100644 index 0000000..88ed6c5 --- /dev/null +++ b/tests/tests2/65_macro_concat_start.expect @@ -0,0 +1 @@ +65_macro_concat_start.c:1: error: '##' invalid at start of macro diff --git a/tests/tests2/66_macro_concat_end.c b/tests/tests2/66_macro_concat_end.c new file mode 100644 index 0000000..55dcaef --- /dev/null +++ b/tests/tests2/66_macro_concat_end.c @@ -0,0 +1,2 @@ +#define paste(A,B) A B## +paste(x,y) diff --git a/tests/tests2/66_macro_concat_end.expect b/tests/tests2/66_macro_concat_end.expect new file mode 100644 index 0000000..224e5c9 --- /dev/null +++ b/tests/tests2/66_macro_concat_end.expect @@ -0,0 +1 @@ +66_macro_concat_end.c:2: error: '##' invalid at end of macro diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 36d84dc..41adb2d 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -79,7 +79,9 @@ TESTS = \ 61_undefined_enum.test \ 62_enumerator_redefinition.test \ 63_local_enumerator_redefinition.test \ - 64_macro_nesting.test + 64_macro_nesting.test \ + 65_macro_concat_start.test \ + 66_macro_concat_end.test # 30_hanoi.test -- seg fault in the code, gcc as well # 34_array_assignment.test -- array assignment is not in C standard -- cgit v1.3.1 From 6e56bb387db8af055ff6de71a23b270de55c3dc8 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 12 Apr 2014 12:00:13 +0800 Subject: Fix preprocessor concat with empty arg --- tcc.h | 1 + tccpp.c | 42 ++++++++++++++++++++++++++++++++----- tests/tests2/67_macro_concat.c | 14 +++++++++++++ tests/tests2/67_macro_concat.expect | 2 ++ tests/tests2/Makefile | 3 ++- 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 tests/tests2/67_macro_concat.c create mode 100644 tests/tests2/67_macro_concat.expect (limited to 'tccpp.c') diff --git a/tcc.h b/tcc.h index 9955839..dda2fc1 100644 --- a/tcc.h +++ b/tcc.h @@ -836,6 +836,7 @@ struct TCCState { /* <-- */ #define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */ +#define TOK_PLCHLDR 0xc1 /* placeholder token as defined in C99 */ #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ #define TOK_ADDC1 0xc3 /* add with carry generation */ #define TOK_ADDC2 0xc4 /* add with carry use */ diff --git a/tccpp.c b/tccpp.c index c8beec5..dfdee50 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2565,7 +2565,8 @@ ST_FUNC void next_nomacro(void) } while (is_space(tok)); } -/* substitute args in macro_str and return allocated string */ +/* substitute arguments in replacement lists in macro_str by the values in + args (field d) and return allocated string */ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) { int last_tok, t, spc; @@ -2622,7 +2623,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) if (gnu_ext && s->type.t && last_tok == TOK_TWOSHARPS && str.len >= 2 && str.str[str.len - 2] == ',') { - if (*st == 0) { + if (*st == TOK_PLCHLDR) { /* suppress ',' '##' */ str.len -= 2; } else { @@ -2793,6 +2794,8 @@ static int macro_subst_tok(TokenString *tok_str, tok_str_add2(&str, tok, &tokc); next_nomacro_spc(); } + if (!str.len) + tok_str_add(&str, TOK_PLCHLDR); str.len -= spc; tok_str_add(&str, 0); sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0); @@ -2885,9 +2888,11 @@ static inline int *macro_twosharps(const int *macro_str) TOK_GET(&t, &ptr, &cval); /* We concatenate the two tokens */ cstr_new(&cstr); - cstr_cat(&cstr, get_tok_str(tok, &tokc)); + if (tok != TOK_PLCHLDR) + cstr_cat(&cstr, get_tok_str(tok, &tokc)); n = cstr.size; - cstr_cat(&cstr, get_tok_str(t, &cval)); + if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR) + cstr_cat(&cstr, get_tok_str(t, &cval)); cstr_ccat(&cstr, '\0'); tcc_open_bf(tcc_state, ":paste:", cstr.size); @@ -2904,8 +2909,35 @@ static inline int *macro_twosharps(const int *macro_str) cstr_free(&cstr); } } - if (tok != TOK_NOSUBST) + if (tok != TOK_NOSUBST) { + const int *oldptr; + CValue cval; + + /* Check if a space need to be added after ## concatenation in + order to avoid misinterpreting the newly formed token + followed by the next token as being a single token (see + macro_concat test) */ + cstr_new(&cstr); + cstr_cat(&cstr, get_tok_str(tok, &tokc)); + oldptr = ptr; + TOK_GET(&t, &ptr, &cval); + ptr = oldptr; + cstr_cat(&cstr, get_tok_str(t, &cval)); + cstr_ccat(&cstr, '\0'); + t = tok; + cval = tokc; + tcc_open_bf(tcc_state, ":paste:", cstr.size); + memcpy(file->buffer, cstr.data, cstr.size); + next_nomacro1(); + if (!*file->buf_ptr) { + tok_str_add2(¯o_str1, t, &cval); + tok = ' '; + } + tcc_close(); + cstr_free(&cstr); + start_of_nosubsts = -1; + } tok_str_add2(¯o_str1, tok, &tokc); } tok_str_add(¯o_str1, 0); diff --git a/tests/tests2/67_macro_concat.c b/tests/tests2/67_macro_concat.c new file mode 100644 index 0000000..c580d3a --- /dev/null +++ b/tests/tests2/67_macro_concat.c @@ -0,0 +1,14 @@ +#include + +#define P(A,B) A ## B ; bob +#define Q(A,B) A ## B+ + +int main(void) +{ + int bob, jim = 21; + bob = P(jim,) *= 2; + printf("jim: %d, bob: %d\n", jim, bob); + jim = 60 Q(+,)3; + printf("jim: %d\n", jim); + return 0; +} diff --git a/tests/tests2/67_macro_concat.expect b/tests/tests2/67_macro_concat.expect new file mode 100644 index 0000000..8386c2d --- /dev/null +++ b/tests/tests2/67_macro_concat.expect @@ -0,0 +1,2 @@ +jim: 21, bob: 42 +jim: 63 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 41adb2d..a7c8a2f 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -81,7 +81,8 @@ TESTS = \ 63_local_enumerator_redefinition.test \ 64_macro_nesting.test \ 65_macro_concat_start.test \ - 66_macro_concat_end.test + 66_macro_concat_end.test \ + 67_macro_concat.test # 30_hanoi.test -- seg fault in the code, gcc as well # 34_array_assignment.test -- array assignment is not in C standard -- cgit v1.3.1 From 6b7a6fcbc8b9ed623a436dc2218cfe31b991037c Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 14 Apr 2014 20:45:10 +0800 Subject: Improve efficiency of macro concatenation As per grischka comment, always output a space after macro concatenation instead of trying to detect if it's necessary as the current approach has a huge cost. --- tccpp.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index dfdee50..2da65cd 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2910,32 +2910,8 @@ static inline int *macro_twosharps(const int *macro_str) } } if (tok != TOK_NOSUBST) { - const int *oldptr; - CValue cval; - - /* Check if a space need to be added after ## concatenation in - order to avoid misinterpreting the newly formed token - followed by the next token as being a single token (see - macro_concat test) */ - cstr_new(&cstr); - cstr_cat(&cstr, get_tok_str(tok, &tokc)); - oldptr = ptr; - TOK_GET(&t, &ptr, &cval); - ptr = oldptr; - cstr_cat(&cstr, get_tok_str(t, &cval)); - cstr_ccat(&cstr, '\0'); - t = tok; - cval = tokc; - tcc_open_bf(tcc_state, ":paste:", cstr.size); - memcpy(file->buffer, cstr.data, cstr.size); - next_nomacro1(); - if (!*file->buf_ptr) { - tok_str_add2(¯o_str1, t, &cval); - tok = ' '; - } - tcc_close(); - cstr_free(&cstr); - + tok_str_add2(¯o_str1, tok, &tokc); + tok = ' '; start_of_nosubsts = -1; } tok_str_add2(¯o_str1, tok, &tokc); -- cgit v1.3.1 From 857f7dbfa65179e6690dbee7ab915fb4458cee11 Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Mon, 28 Apr 2014 12:42:36 +0800 Subject: update static void parse_number(const char *p) for tccpp.c --- tccpp.c | 360 +++++++++++++++++++++++++--------------------------------------- 1 file changed, 139 insertions(+), 221 deletions(-) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index 2da65cd..938699e 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1817,234 +1817,152 @@ static void bn_zero(unsigned int *bn) current token */ static void parse_number(const char *p) { - int b, t, shift, frac_bits, s, exp_val, ch; - char *q; - unsigned int bn[BN_SIZE]; - double d; - - /* number */ - q = token_buf; - ch = *p++; - t = ch; - ch = *p++; - *q++ = t; + int b, t, c; + + c = *p++; + t = *p++; b = 10; - if (t == '.') { - goto float_frac_parse; - } else if (t == '0') { - if (ch == 'x' || ch == 'X') { - q--; - ch = *p++; + if(c=='.'){ + --p; + goto float_frac_parse; + } + if(c == '0'){ + if (t == 'x' || t == 'X') { b = 16; - } else if (tcc_ext && (ch == 'b' || ch == 'B')) { - q--; - ch = *p++; + c = *p++; + } else if (tcc_ext && (t == 'b' || t == 'B')) { b = 2; - } - } - /* parse all digits. cannot check octal numbers at this stage - because of floating point constants */ - while (1) { - if (ch >= 'a' && ch <= 'f') - t = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') - t = ch - 'A' + 10; - else if (isnum(ch)) - t = ch - '0'; - else - break; - if (t >= b) - break; - if (q >= token_buf + STRING_MAX_SIZE) { - num_too_long: - tcc_error("number too long"); - } - *q++ = ch; - ch = *p++; - } - if (ch == '.' || - ((ch == 'e' || ch == 'E') && b == 10) || - ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) { - if (b != 10) { - /* NOTE: strtox should support that for hexa numbers, but - non ISOC99 libcs do not support it, so we prefer to do - it by hand */ - /* hexadecimal or binary floats */ - /* XXX: handle overflows */ - *q = '\0'; - if (b == 16) - shift = 4; - else - shift = 2; - bn_zero(bn); - q = token_buf; - while (1) { - t = *q++; - if (t == '\0') { - break; - } else if (t >= 'a') { - t = t - 'a' + 10; - } else if (t >= 'A') { - t = t - 'A' + 10; - } else { - t = t - '0'; - } - bn_lshift(bn, shift, t); - } - frac_bits = 0; - if (ch == '.') { - ch = *p++; - while (1) { - t = ch; - if (t >= 'a' && t <= 'f') { - t = t - 'a' + 10; - } else if (t >= 'A' && t <= 'F') { - t = t - 'A' + 10; - } else if (t >= '0' && t <= '9') { - t = t - '0'; - } else { - break; - } - if (t >= b) - tcc_error("invalid digit"); - bn_lshift(bn, shift, t); - frac_bits += shift; - ch = *p++; - } - } - if (ch != 'p' && ch != 'P') + c = *p++; + }else{ + --p; + } + }else + --p; + if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) || + ((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){ + long double ld, sh, fb; + int exp; + /* NOTE: strtox should support that for hexa numbers, but + non ISOC99 libcs do not support it, so we prefer to do + it by hand */ + /* hexadecimal or binary floats */ + /* XXX: handle overflows */ +float_frac_parse: + fb = 1.0L/b; + sh = b; + ld = 0.0; + + while(1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if(isnum(c)) + t = c - '0'; + else + break; + if (t >= b) + tcc_error("invalid digit"); + ld = ld * b + t; + c = *p++; + } + if (c == '.'){ + c = *p++; + sh = fb; + while (1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if (isnum(c)) + t =c - '0'; + else + break; + if (t >= b){ + if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F')) + break; + tcc_error("invalid digit"); + } + ld += sh*t; + sh*=fb; + c = *p++; + } + } + if ((b == 16 || b == 2) && c != 'p' && c != 'P') expect("exponent"); - ch = *p++; - s = 1; - exp_val = 0; - if (ch == '+') { - ch = *p++; - } else if (ch == '-') { - s = -1; - ch = *p++; - } - if (ch < '0' || ch > '9') - expect("exponent digits"); - while (ch >= '0' && ch <= '9') { - exp_val = exp_val * 10 + ch - '0'; - ch = *p++; - } - exp_val = exp_val * s; - - /* now we can generate the number */ - /* XXX: should patch directly float number */ - d = (double)bn[1] * 4294967296.0 + (double)bn[0]; - d = ldexp(d, exp_val - frac_bits); - t = toup(ch); - if (t == 'F') { - ch = *p++; - tok = TOK_CFLOAT; - /* float : should handle overflow */ - tokc.f = (float)d; - } else if (t == 'L') { - ch = *p++; + if(((c == 'e' || c == 'E') && b == 10) || + ((c == 'p' || c == 'P') && (b == 16 || b == 2))){ + c = *p++; + if(c == '+' || c == '-'){ + if (c == '-') + sh = fb; + c = *p++; + }else + sh = b; + if (!isnum(c)) + expect("exponent digits"); + exp = 0; + do{ + exp = exp * 10 + c - '0'; + c = *p++; + }while(isnum(c)); + while (exp != 0){ + if (exp & 1) + ld *= sh; + exp >>= 1; + sh *= sh; + } + } + t = toup(c); + if (t == 'F') { + c = *p++; + tok = TOK_CFLOAT; + tokc.f = (float)ld; + } else if (t == 'L') { + c = *p++; #ifdef TCC_TARGET_PE - tok = TOK_CDOUBLE; - tokc.d = d; + tok = TOK_CDOUBLE; + tokc.d = (double)ld; #else - tok = TOK_CLDOUBLE; - /* XXX: not large enough */ - tokc.ld = (long double)d; + tok = TOK_CLDOUBLE; + tokc.ld = ld; #endif - } else { - tok = TOK_CDOUBLE; - tokc.d = d; - } - } else { - /* decimal floats */ - if (ch == '.') { - if (q >= token_buf + STRING_MAX_SIZE) - goto num_too_long; - *q++ = ch; - ch = *p++; - float_frac_parse: - while (ch >= '0' && ch <= '9') { - if (q >= token_buf + STRING_MAX_SIZE) - goto num_too_long; - *q++ = ch; - ch = *p++; - } - } - if (ch == 'e' || ch == 'E') { - if (q >= token_buf + STRING_MAX_SIZE) - goto num_too_long; - *q++ = ch; - ch = *p++; - if (ch == '-' || ch == '+') { - if (q >= token_buf + STRING_MAX_SIZE) - goto num_too_long; - *q++ = ch; - ch = *p++; - } - if (ch < '0' || ch > '9') - expect("exponent digits"); - while (ch >= '0' && ch <= '9') { - if (q >= token_buf + STRING_MAX_SIZE) - goto num_too_long; - *q++ = ch; - ch = *p++; - } - } - *q = '\0'; - t = toup(ch); - errno = 0; - if (t == 'F') { - ch = *p++; - tok = TOK_CFLOAT; - tokc.f = strtof(token_buf, NULL); - } else if (t == 'L') { - ch = *p++; -#ifdef TCC_TARGET_PE - tok = TOK_CDOUBLE; - tokc.d = strtod(token_buf, NULL); -#else - tok = TOK_CLDOUBLE; - tokc.ld = strtold(token_buf, NULL); -#endif - } else { - tok = TOK_CDOUBLE; - tokc.d = strtod(token_buf, NULL); - } - } + } else { + tok = TOK_CDOUBLE; + tokc.d = (double)ld; + } } else { - unsigned long long n, n1; + uint64_t n = 0, n1; + int warn = 1; int lcount, ucount; - - /* integer number */ - *q = '\0'; - q = token_buf; - if (b == 10 && *q == '0') { + if (b == 10 && c == '0') { b = 8; - q++; - } - n = 0; - while(1) { - t = *q++; - /* no need for checks except for base 10 / 8 errors */ - if (t == '\0') { - break; - } else if (t >= 'a') { - t = t - 'a' + 10; - } else if (t >= 'A') { - t = t - 'A' + 10; - } else { - t = t - '0'; - if (t >= b) - tcc_error("invalid digit"); - } - n1 = n; - n = n * b + t; - /* detect overflow */ - /* XXX: this test is not reliable */ - if (n < n1) - tcc_error("integer constant overflow"); } - + while(1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if(isnum(c)) + t = c - '0'; + else + break; + if (t >= b) + tcc_error("invalid digit"); + n1 = n; + n = n * b + t; + if (n < n1 && warn){ + tcc_warning("integer constant overflow"); + warn = 0; + } + c = *p++; + } /* XXX: not exactly ANSI compliant */ if ((n & 0xffffffff00000000LL) != 0) { if ((n >> 63) != 0) @@ -2059,7 +1977,7 @@ static void parse_number(const char *p) lcount = 0; ucount = 0; for(;;) { - t = toup(ch); + t = toup(c); if (t == 'L') { if (lcount >= 2) tcc_error("three 'l's in integer constant"); @@ -2074,7 +1992,7 @@ static void parse_number(const char *p) #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE } #endif - ch = *p++; + c = *p++; } else if (t == 'U') { if (ucount >= 1) tcc_error("two 'u's in integer constant"); @@ -2083,7 +2001,7 @@ static void parse_number(const char *p) tok = TOK_CUINT; else if (tok == TOK_CLLONG) tok = TOK_CULLONG; - ch = *p++; + c = *p++; } else { break; } @@ -2093,7 +2011,7 @@ static void parse_number(const char *p) else tokc.ull = n; } - if (ch) + if (c) tcc_error("invalid number\n"); } -- cgit v1.3.1 From deaee6c2496ecb25858290405fef8ef79aece979 Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Mon, 28 Apr 2014 12:53:18 +0800 Subject: fix tccpp.c --- tccpp.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'tccpp.c') diff --git a/tccpp.c b/tccpp.c index 938699e..732c5ea 100644 --- a/tccpp.c +++ b/tccpp.c @@ -58,7 +58,6 @@ static const int *unget_saved_macro_ptr; static int unget_saved_buffer[TOK_MAX_SIZE + 1]; static int unget_buffer_enabled; static TokenSym *hash_ident[TOK_HASH_SIZE]; -static char token_buf[STRING_MAX_SIZE + 1]; /* true if isid(c) || isnum(c) */ static unsigned char isidnum_table[256-CH_EOF]; @@ -1790,29 +1789,6 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long cstr_wccat(outstr, '\0'); } -/* we use 64 bit numbers */ -#define BN_SIZE 2 - -/* bn = (bn << shift) | or_val */ -static void bn_lshift(unsigned int *bn, int shift, int or_val) -{ - int i; - unsigned int v; - for(i=0;i> (32 - shift); - } -} - -static void bn_zero(unsigned int *bn) -{ - int i; - for(i=0;i