- tcc -vv: show cross-libtcc1.a correctly (and more)

(As long as it is in the default install location and was not
moved elsewhere into the library search path manually)

Also:
- libtcc.c:
  - error1(): show correct line with "In file included from ..."
  - support "tcc -Bxxx -vv"
  - tcc_new()/tcc_compile(): Don't create elf sections for tcc -E
- tccdbg.c:
  - tcc -E -g : revert 1de025c13a
    Let's keep things simple, everybody understands 'do_debug'
    and dState is set by tcov too (but no debug sections).
- tccgen.c:
  - avoid the extra parameter for gind()
    (from c3e3a07ed4)
  - vla func params: use skip_or_save_block() and enable
    VT_LVAL (see 313855c232)
  - cleanup nocode_wanted a bit
- tccelf.c:
  - tccelf_end_file(): don't try to translate zero-sym relocs
    (seems to happen with asm "jmp 0x1000")
  - version_add(): do not make "ld-linux.so" DT_NEEDED
This commit is contained in:
grischka 2022-08-20 12:58:56 +02:00
parent 414c22c67b
commit e41730f11a
9 changed files with 137 additions and 111 deletions

View file

@ -572,7 +572,7 @@ static void error1(int mode, const char *fmt, va_list ap)
if (f) { if (f) {
for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
cstr_printf(&cs, "In file included from %s:%d:\n", cstr_printf(&cs, "In file included from %s:%d:\n",
(*pf)->filename, (*pf)->line_num); (*pf)->filename, (*pf)->line_num - 1);
cstr_printf(&cs, "%s:%d: ", cstr_printf(&cs, "%s:%d: ",
f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL)); f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
} else if (s1->current_filename) { } else if (s1->current_filename) {
@ -733,24 +733,25 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
file->fd = fd; file->fd = fd;
} }
tccelf_begin_file(s1);
preprocess_start(s1, filetype); preprocess_start(s1, filetype);
tccgen_init(s1); tccgen_init(s1);
if (s1->output_type == TCC_OUTPUT_PREPROCESS) { if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
tcc_preprocess(s1); tcc_preprocess(s1);
} else if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP)) {
tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
} else { } else {
tccgen_compile(s1); tccelf_begin_file(s1);
if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP)) {
tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
} else {
tccgen_compile(s1);
}
tccelf_end_file(s1);
} }
} }
tccgen_finish(s1); tccgen_finish(s1);
preprocess_end(s1); preprocess_end(s1);
s1->error_set_jmp_enabled = 0; s1->error_set_jmp_enabled = 0;
tcc_exit_state(s1); tcc_exit_state(s1);
tccelf_end_file(s1);
return s1->nb_errors != 0 ? -1 : 0; return s1->nb_errors != 0 ? -1 : 0;
} }
@ -819,8 +820,6 @@ LIBTCCAPI TCCState *tcc_new(void)
/* might be used in error() before preprocess_start() */ /* might be used in error() before preprocess_start() */
s->include_stack_ptr = s->include_stack; s->include_stack_ptr = s->include_stack;
tccelf_new(s);
tcc_set_lib_path(s, CONFIG_TCCDIR); tcc_set_lib_path(s, CONFIG_TCCDIR);
return s; return s;
} }
@ -879,19 +878,23 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
} }
if (output_type == TCC_OUTPUT_PREPROCESS) if (output_type == TCC_OUTPUT_PREPROCESS) {
s->do_debug = 0;
return 0; return 0;
}
tccelf_new(s);
if (s->do_debug) {
/* add debug sections */
tcc_debug_new(s);
}
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (s->do_bounds_check) { if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */ /* if bound checking, then add corresponding sections */
tccelf_bounds_new(s); tccelf_bounds_new(s);
} }
#endif #endif
if (s->do_debug) {
/* add debug sections */
tcc_debug_new(s);
}
if (output_type == TCC_OUTPUT_OBJ) { if (output_type == TCC_OUTPUT_OBJ) {
/* always elf for objects */ /* always elf for objects */
s->output_format = TCC_OUTPUT_FORMAT_ELF; s->output_format = TCC_OUTPUT_FORMAT_ELF;
@ -1195,11 +1198,9 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
/* find [cross-]libtcc1.a and tcc helper objects in library path */ /* find [cross-]libtcc1.a and tcc helper objects in library path */
ST_FUNC void tcc_add_support(TCCState *s1, const char *filename) ST_FUNC void tcc_add_support(TCCState *s1, const char *filename)
{ {
#ifdef CONFIG_TCC_CROSSPREFIX
char buf[100]; char buf[100];
snprintf(buf, sizeof buf, "%s%s", CONFIG_TCC_CROSSPREFIX, filename); if (CONFIG_TCC_CROSSPREFIX[0])
filename = buf; filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
#endif
if (tcc_add_dll(s1, filename, 0) < 0) if (tcc_add_dll(s1, filename, 0) < 0)
tcc_error_noabort("%s not found", filename); tcc_error_noabort("%s not found", filename);
} }
@ -1838,6 +1839,7 @@ reparse:
case TCC_OPTION_B: case TCC_OPTION_B:
/* set tcc utilities path (mainly for tcc development) */ /* set tcc utilities path (mainly for tcc development) */
tcc_set_lib_path(s, optarg); tcc_set_lib_path(s, optarg);
++noaction;
break; break;
case TCC_OPTION_l: case TCC_OPTION_l:
args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK)); args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));

8
tcc.c
View file

@ -206,10 +206,8 @@ static void print_search_dirs(TCCState *s)
/* print_dirs("programs", NULL, 0); */ /* print_dirs("programs", NULL, 0); */
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths); print_dirs("libraries", s->library_paths, s->nb_library_paths);
#ifdef TCC_TARGET_PE printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path); #ifndef TCC_TARGET_PE
#else
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
print_dirs("crt", s->crt_paths, s->nb_crt_paths); print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
#endif #endif
@ -281,7 +279,7 @@ int main(int argc0, char **argv0)
redo: redo:
argc = argc0, argv = argv0; argc = argc0, argv = argv0;
s = s1 = tcc_new(); s = s1 = tcc_new();
#ifdef CONFIG_TCC_SWITCHES #ifdef CONFIG_TCC_SWITCHES /* predefined options */
tcc_set_options(s, CONFIG_TCC_SWITCHES); tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif #endif
opt = tcc_parse_args(s, &argc, &argv, 1); opt = tcc_parse_args(s, &argc, &argv, 1);

4
tcc.h
View file

@ -361,6 +361,10 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define TCC_LIBTCC1 "libtcc1.a" # define TCC_LIBTCC1 "libtcc1.a"
#endif #endif
#ifndef CONFIG_TCC_CROSSPREFIX
# define CONFIG_TCC_CROSSPREFIX ""
#endif
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC #if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
#define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" #define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"

View file

@ -666,7 +666,7 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
SHN_ABS, filename); SHN_ABS, filename);
if (s1->dState) { if (s1->do_debug) {
new_file = last_line_num = 0; new_file = last_line_num = 0;
debug_next_type = N_DEFAULT_DEBUG; debug_next_type = N_DEFAULT_DEBUG;
@ -835,7 +835,7 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
/* put end of translation unit info */ /* put end of translation unit info */
ST_FUNC void tcc_debug_end(TCCState *s1) ST_FUNC void tcc_debug_end(TCCState *s1)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (s1->dwarf) { if (s1->dwarf) {
int i, j; int i, j;
@ -992,7 +992,7 @@ ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename)
if (0 == strcmp(file->filename, filename)) if (0 == strcmp(file->filename, filename))
return; return;
pstrcpy(file->filename, sizeof(file->filename), filename); pstrcpy(file->filename, sizeof(file->filename), filename);
if (!s1->dState) if (!s1->do_debug)
return; return;
if (s1->dwarf) if (s1->dwarf)
dwarf_file(s1); dwarf_file(s1);
@ -1002,7 +1002,7 @@ ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename)
/* begin of #include */ /* begin of #include */
ST_FUNC void tcc_debug_bincl(TCCState *s1) ST_FUNC void tcc_debug_bincl(TCCState *s1)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (s1->dwarf) { if (s1->dwarf) {
int i, j; int i, j;
@ -1059,7 +1059,7 @@ ST_FUNC void tcc_debug_bincl(TCCState *s1)
/* end of #include */ /* end of #include */
ST_FUNC void tcc_debug_eincl(TCCState *s1) ST_FUNC void tcc_debug_eincl(TCCState *s1)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (s1->dwarf) if (s1->dwarf)
dwarf_file(s1); dwarf_file(s1);
@ -1073,7 +1073,7 @@ ST_FUNC void tcc_debug_line(TCCState *s1)
{ {
BufferedFile *f; BufferedFile *f;
if (!s1->dState) if (!s1->do_debug)
return; return;
if (cur_text_section != text_section) if (cur_text_section != text_section)
return; return;
@ -1161,7 +1161,7 @@ static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned l
ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value) ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (type == N_LBRAC) { if (type == N_LBRAC) {
struct _debug_info *info = struct _debug_info *info =
@ -1234,7 +1234,7 @@ ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t)
{ {
int i, j, debug_type; int i, j, debug_type;
if (!s1->dState || !s1->dwarf || debug_info) if (!s1->do_debug || !s1->dwarf || debug_info)
return; return;
if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1) if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1)
for (i = 0; i < n_debug_anon_hash; i++) for (i = 0; i < n_debug_anon_hash; i++)
@ -1747,7 +1747,7 @@ static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur)
ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e) ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e)
{ {
CString debug_str; CString debug_str;
if (!s1->dState) if (!s1->do_debug)
return; return;
cstr_new (&debug_str); cstr_new (&debug_str);
for (; s != e; s = s->prev) { for (; s != e; s = s->prev) {
@ -1777,7 +1777,7 @@ ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym)
CString debug_str; CString debug_str;
BufferedFile *f; BufferedFile *f;
if (!s1->dState) if (!s1->do_debug)
return; return;
debug_info_root = NULL; debug_info_root = NULL;
debug_info = NULL; debug_info = NULL;
@ -1816,7 +1816,7 @@ ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym)
/* put function size */ /* put function size */
ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) ST_FUNC void tcc_debug_funcend(TCCState *s1, int size)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
tcc_debug_line(s1); tcc_debug_line(s1);
tcc_debug_stabn(s1, N_RBRAC, size); tcc_debug_stabn(s1, N_RBRAC, size);
@ -1873,7 +1873,7 @@ ST_FUNC void tcc_debug_funcend(TCCState *s1, int size)
ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type) ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM) if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM)
return; return;
@ -1925,7 +1925,7 @@ ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bi
ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym) ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym)
{ {
if (!s1->dState) if (!s1->do_debug)
return; return;
if (s1->dwarf) { if (s1->dwarf) {
int debug_type; int debug_type;

View file

@ -187,7 +187,8 @@ ST_FUNC void tccelf_end_file(TCCState *s1)
ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset); ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset);
for (; rel < rel_end; ++rel) { for (; rel < rel_end; ++rel) {
int n = ELFW(R_SYM)(rel->r_info) - first_sym; int n = ELFW(R_SYM)(rel->r_info) - first_sym;
//if (n < 0) tcc_error("internal: invalid symbol index in relocation"); if (n < 0) /* zero sym_index in reloc (can happen with asm) */
continue;
rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info)); rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info));
} }
} }
@ -596,8 +597,14 @@ version_add (TCCState *s1)
ElfW(Vernaux) *vna = 0; ElfW(Vernaux) *vna = 0;
if (sv->out_index < 1) if (sv->out_index < 1)
continue; continue;
/* make sure that a DT_NEEDED tag is put */ /* make sure that a DT_NEEDED tag is put */
tcc_add_dllref(s1, sv->lib, 0); /* abitest-tcc fails on older i386-linux with "ld-linux.so.2" DT_NEEDED
ret_int_test... Inconsistency detected by ld.so: dl-minimal.c: 148:
realloc: Assertion `ptr == alloc_last_block' failed! */
if (strcmp(sv->lib, "ld-linux.so.2"))
tcc_add_dllref(s1, sv->lib, 0);
vnofs = section_add(verneed_section, sizeof(*vn), 1); vnofs = section_add(verneed_section, sizeof(*vn), 1);
vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
vn->vn_version = 1; vn->vn_version = 1;

147
tccgen.c
View file

@ -54,33 +54,10 @@ ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* no code generation wanted */ ST_DATA int nocode_wanted; /* no code generation wanted */
#define unevalmask 0xffff /* unevaluated subexpression */ #define unevalmask 0xffff /* unevaluated subexpression */
#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
#define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ #define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
/* Automagical code suppression ----> */
#define CODE_OFF() (nocode_wanted |= 0x20000000) #define CODE_OFF() (nocode_wanted |= 0x20000000)
#define CODE_ON() (nocode_wanted &= ~0x20000000) #define CODE_ON() (nocode_wanted &= ~0x20000000)
/* Clear 'nocode_wanted' at label if it was used */
ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }}
static int gind(int known_unreachable)
{
int t = ind;
if (!known_unreachable)
CODE_ON();
if (debug_modes)
tcc_tcov_block_begin(tcc_state);
return t;
}
/* Set 'nocode_wanted' after unconditional jumps */
static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }
static int gjmp_acs(int t) { t = gjmp(t); CODE_OFF(); return t; }
/* These are #undef'd at the end of this file */
#define gjmp_addr gjmp_addr_acs
#define gjmp gjmp_acs
/* <---- */
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
@ -170,6 +147,46 @@ static int get_temp_local_var(int size,int align);
static void clear_temp_local_var_list(); static void clear_temp_local_var_list();
static void cast_error(CType *st, CType *dt); static void cast_error(CType *st, CType *dt);
/* ------------------------------------------------------------------------- */
/* Automagical code suppression */
/* Clear 'nocode_wanted' at forward label if it was used */
ST_FUNC void gsym(int t)
{
if (t) {
gsym_addr(t, ind);
CODE_ON();
}
}
/* Clear 'nocode_wanted' if current pc is a label */
static int gind()
{
int t = ind;
CODE_ON();
if (debug_modes)
tcc_tcov_block_begin(tcc_state);
return t;
}
/* Set 'nocode_wanted' after unconditional (backwards) jump */
static void gjmp_addr_acs(int t)
{
gjmp_addr(t);
CODE_OFF();
}
/* Set 'nocode_wanted' after unconditional (forwards) jump */
static int gjmp_acs(int t)
{
t = gjmp(t);
CODE_OFF();
return t;
}
/* These are #undef'd at the end of this file */
#define gjmp_addr gjmp_addr_acs
#define gjmp gjmp_acs
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
ST_INLN int is_float(int t) ST_INLN int is_float(int t)
@ -358,7 +375,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
func_ind = -1; func_ind = -1;
anon_sym = SYM_FIRST_ANOM; anon_sym = SYM_FIRST_ANOM;
const_wanted = 0; const_wanted = 0;
nocode_wanted = 0x80000000; nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
local_scope = 0; local_scope = 0;
debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1; debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
@ -3126,7 +3143,7 @@ error:
} }
/* cannot generate code for global or static initializers */ /* cannot generate code for global or static initializers */
if (STATIC_DATA_WANTED) if (nocode_wanted & DATA_ONLY_WANTED)
goto done; goto done;
/* non constant case: generate code */ /* non constant case: generate code */
@ -4728,7 +4745,7 @@ static int asm_label_instr(void)
static int post_type(CType *type, AttributeDef *ad, int storage, int td) static int post_type(CType *type, AttributeDef *ad, int storage, int td)
{ {
int n, l, t1, arg_size, align, unused_align; int n, l, t1, arg_size, align;
Sym **plast, *s, *first; Sym **plast, *s, *first;
AttributeDef ad1; AttributeDef ad1;
CType pt; CType pt;
@ -4775,7 +4792,10 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
expect("identifier"); expect("identifier");
convert_parameter_type(&pt); convert_parameter_type(&pt);
arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
s = sym_push(n, &pt, 0, 0); /* these symbols may be evaluated for VLArrays (see below, under
nocode_wanted) which is why we push them here as normal symbols
temporarily. Example: int func(int a, int b[++a]); */
s = sym_push(n, &pt, VT_LOCAL|VT_LVAL, 0);
*plast = s; *plast = s;
plast = &s->next; plast = &s->next;
if (tok == ')') if (tok == ')')
@ -4842,26 +4862,11 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
break; break;
} }
if (tok != ']') { if (tok != ']') {
int nest = 1;
/* Code generation is not done now but has to be done /* Code generation is not done now but has to be done
at start of function. Save code here for later use. */ at start of function. Save code here for later use. */
nocode_wanted = 1; nocode_wanted = 1;
vla_array_tok = tok_str_alloc(); skip_or_save_block(&vla_array_tok);
for (;;) {
if (tok == ']') {
nest--;
if (nest == 0)
break;
}
if (tok == '[')
nest++;
tok_str_add_tok(vla_array_tok);
next();
}
unget_tok(0); unget_tok(0);
tok_str_add(vla_array_tok, -1);
tok_str_add(vla_array_tok, 0);
vla_array_str = vla_array_tok->str; vla_array_str = vla_array_tok->str;
begin_macro(vla_array_tok, 2); begin_macro(vla_array_tok, 2);
next(); next();
@ -4902,7 +4907,7 @@ check:
if ((type->t & VT_BTYPE) == VT_FUNC) if ((type->t & VT_BTYPE) == VT_FUNC)
tcc_error("declaration of an array of functions"); tcc_error("declaration of an array of functions");
if ((type->t & VT_BTYPE) == VT_VOID if ((type->t & VT_BTYPE) == VT_VOID
|| type_size(type, &unused_align) < 0) || type_size(type, &align) < 0)
tcc_error("declaration of an array of incomplete type elements"); tcc_error("declaration of an array of incomplete type elements");
t1 |= type->t & VT_VLA; t1 |= type->t & VT_VLA;
@ -4933,7 +4938,8 @@ check:
s = sym_push(SYM_FIELD, type, 0, n); s = sym_push(SYM_FIELD, type, 0, n);
type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR; type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
type->ref = s; type->ref = s;
if (vla_array_str) {
if (vla_array_str) {
if (t1 & VT_VLA) if (t1 & VT_VLA)
s->vla_array_str = vla_array_str; s->vla_array_str = vla_array_str;
else else
@ -6783,7 +6789,7 @@ again:
} }
} else if (t == TOK_WHILE) { } else if (t == TOK_WHILE) {
d = gind(0); d = gind();
skip('('); skip('(');
gexpr(); gexpr();
skip(')'); skip(')');
@ -6883,7 +6889,7 @@ again:
} }
skip(';'); skip(';');
a = b = 0; a = b = 0;
c = d = gind(0); c = d = gind();
if (tok != ';') { if (tok != ';') {
gexpr(); gexpr();
a = gvtst(1, 0); a = gvtst(1, 0);
@ -6891,7 +6897,7 @@ again:
skip(';'); skip(';');
if (tok != ')') { if (tok != ')') {
e = gjmp(0); e = gjmp(0);
d = gind(0); d = gind();
gexpr(); gexpr();
vpop(); vpop();
gjmp_addr(c); gjmp_addr(c);
@ -6906,7 +6912,7 @@ again:
} else if (t == TOK_DO) { } else if (t == TOK_DO) {
a = b = 0; a = b = 0;
d = gind(0); d = gind();
lblock(&a, &b); lblock(&a, &b);
gsym(b); gsym(b);
skip(TOK_WHILE); skip(TOK_WHILE);
@ -6940,17 +6946,17 @@ again:
/* case lookup */ /* case lookup */
gsym(b); gsym(b);
if (sw->nocode_wanted)
goto skip_switch;
if (sw->sv.type.t & VT_UNSIGNED) if (sw->sv.type.t & VT_UNSIGNED)
qsort(sw->p, sw->n, sizeof(void*), case_cmpu); qsort(sw->p, sw->n, sizeof(void*), case_cmpu);
else else
qsort(sw->p, sw->n, sizeof(void*), case_cmpi); qsort(sw->p, sw->n, sizeof(void*), case_cmpi);
for (b = 1; b < sw->n; b++) for (b = 1; b < sw->n; b++)
if (sw->sv.type.t & VT_UNSIGNED if (sw->sv.type.t & VT_UNSIGNED
? (uint64_t)sw->p[b - 1]->v2 >= (uint64_t)sw->p[b]->v1 ? (uint64_t)sw->p[b - 1]->v2 >= (uint64_t)sw->p[b]->v1
: sw->p[b - 1]->v2 >= sw->p[b]->v1) : sw->p[b - 1]->v2 >= sw->p[b]->v1)
tcc_error("duplicate case value"); tcc_error("duplicate case value");
vpushv(&sw->sv); vpushv(&sw->sv);
gv(RC_INT); gv(RC_INT);
d = 0, gcase(sw->p, sw->n, &d); d = 0, gcase(sw->p, sw->n, &d);
@ -6959,6 +6965,7 @@ again:
gsym_addr(d, sw->def_sym); gsym_addr(d, sw->def_sym);
else else
gsym(d); gsym(d);
skip_switch:
/* break label */ /* break label */
gsym(a); gsym(a);
@ -6978,9 +6985,9 @@ again:
|| (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1))
tcc_warning("empty case range"); tcc_warning("empty case range");
} }
if (debug_modes) /* case and default are unreachable from a switch under nocode_wanted */
tcc_tcov_reset_ind(tcc_state); if (!cur_switch->nocode_wanted)
cr->sym = gind(cur_switch->nocode_wanted); cr->sym = gind();
dynarray_add(&cur_switch->p, &cur_switch->n, cr); dynarray_add(&cur_switch->p, &cur_switch->n, cr);
skip(':'); skip(':');
is_expr = 0; is_expr = 0;
@ -6991,9 +6998,7 @@ again:
expect("switch"); expect("switch");
if (cur_switch->def_sym) if (cur_switch->def_sym)
tcc_error("too many 'default'"); tcc_error("too many 'default'");
if (debug_modes) cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
tcc_tcov_reset_ind(tcc_state);
cur_switch->def_sym = gind(cur_switch->nocode_wanted);
skip(':'); skip(':');
is_expr = 0; is_expr = 0;
goto block_after_label; goto block_after_label;
@ -7059,7 +7064,7 @@ again:
} else { } else {
s = label_push(&global_label_stack, t, LABEL_DEFINED); s = label_push(&global_label_stack, t, LABEL_DEFINED);
} }
s->jnext = gind(0); s->jnext = gind();
s->cleanupstate = cur_scope->cl.s; s->cleanupstate = cur_scope->cl.s;
block_after_label: block_after_label:
@ -7068,6 +7073,8 @@ again:
AttributeDef ad_tmp; AttributeDef ad_tmp;
parse_attribute(&ad_tmp); parse_attribute(&ad_tmp);
} }
if (debug_modes)
tcc_tcov_reset_ind(tcc_state);
vla_restore(cur_scope->vla.loc); vla_restore(cur_scope->vla.loc);
if (tok != '}') if (tok != '}')
goto again; goto again;
@ -7107,9 +7114,16 @@ static void skip_or_save_block(TokenString **str)
if (str) if (str)
*str = tok_str_alloc(); *str = tok_str_alloc();
while ((level > 0 || (tok != '}' && tok != ',' && tok != ';' && tok != ')'))) { while (1) {
int t; int t = tok;
if (tok == TOK_EOF) { if (level == 0
&& (t == ','
|| t == ';'
|| t == '}'
|| t == ')'
|| t == ']'))
break;
if (t == TOK_EOF) {
if (str || level > 0) if (str || level > 0)
tcc_error("unexpected end of file"); tcc_error("unexpected end of file");
else else
@ -7117,11 +7131,10 @@ static void skip_or_save_block(TokenString **str)
} }
if (str) if (str)
tok_str_add_tok(*str); tok_str_add_tok(*str);
t = tok;
next(); next();
if (t == '{' || t == '(') { if (t == '{' || t == '(' || t == '[') {
level++; level++;
} else if (t == '}' || t == ')') { } else if (t == '}' || t == ')' || t == ']') {
level--; level--;
if (level == 0 && braces && t == '}') if (level == 0 && braces && t == '}')
break; break;
@ -7798,7 +7811,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
/* Always allocate static or global variables */ /* Always allocate static or global variables */
if (v && (r & VT_VALMASK) == VT_CONST) if (v && (r & VT_VALMASK) == VT_CONST)
nocode_wanted |= 0x80000000; nocode_wanted |= DATA_ONLY_WANTED;
flexible_array = NULL; flexible_array = NULL;
size = type_size(type, &align); size = type_size(type, &align);
@ -8136,7 +8149,7 @@ static void gen_function(Sym *sym)
func_var = 0; /* for safety */ func_var = 0; /* for safety */
ind = 0; /* for safety */ ind = 0; /* for safety */
func_ind = -1; func_ind = -1;
nocode_wanted = 0x80000000; nocode_wanted = DATA_ONLY_WANTED;
check_vstack(); check_vstack();
/* do this after funcend debug info */ /* do this after funcend debug info */
next(); next();

View file

@ -838,6 +838,7 @@ static uint8_t *parse_pp_string(uint8_t *p, int sep, CString *str)
if (c == CH_EOF) { if (c == CH_EOF) {
unterminated_string: unterminated_string:
/* XXX: indicate line number of start of string */ /* XXX: indicate line number of start of string */
tok_flags &= ~TOK_FLAG_BOL;
tcc_error("missing terminating %c character", sep); tcc_error("missing terminating %c character", sep);
} else if (c == '\\') { } else if (c == '\\') {
if (str) if (str)

View file

@ -3032,9 +3032,9 @@ void c99_vla_test_3d(int s, int arr[2][3][s])
printf ("%d\n", arr[1][2][3]); printf ("%d\n", arr[1][2][3]);
} }
void c99_vla_test_3e(int s, int arr[][3][s]) void c99_vla_test_3e(int s, int arr[][3][--s])
{ {
printf ("%d\n", arr[1][2][3]); printf ("%d %d\n", s, arr[1][2][3]);
} }
void c99_vla_test_3(void) void c99_vla_test_3(void)
@ -3042,12 +3042,12 @@ void c99_vla_test_3(void)
int a[2][3][4]; int a[2][3][4];
memset (a, 0, sizeof(a)); memset (a, 0, sizeof(a));
a[1][2][3] = 2; a[1][2][3] = 123;
c99_vla_test_3a(a); c99_vla_test_3a(a);
c99_vla_test_3b(2, a); c99_vla_test_3b(2, a);
c99_vla_test_3c(3, a); c99_vla_test_3c(3, a);
c99_vla_test_3d(4, a); c99_vla_test_3d(4, a);
c99_vla_test_3e(4, a); c99_vla_test_3e(5, a);
} }
void c99_vla_test(void) void c99_vla_test(void)

View file

@ -1150,6 +1150,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
size = type_size(ty, &align); size = type_size(ty, &align);
*psize = (size + 7) & ~7; *psize = (size + 7) & ~7;
*palign = (align + 7) & ~7; *palign = (align + 7) & ~7;
*reg_count = 0; /* avoid compiler warning */
if (size > 16) { if (size > 16) {
mode = x86_64_mode_memory; mode = x86_64_mode_memory;