tccpp: fix issues, add tests

* fix some macro expansion issues
* add some pp tests in tests/pp
* improved tcc -E output for better diff'ability
* remove -dD feature (quirky code, exotic feature,
  didn't work well)

Based partially on ideas / researches from PipCet

Some issues remain with VA_ARGS macros (if used in a
rather tricky way).

Also, to keep it simple, the pp doesn't automtically
add any extra spaces to separate tokens which otherwise
would form wrong tokens if re-read from tcc -E output
(such as '+' '=')  GCC does that, other compilers don't.

 * cleanups
  - #line 01 "file" / # 01 "file" processing
  - #pragma comment(lib,"foo")
  - tcc -E: forward some pragmas to output (pack, comment(lib))
  - fix macro parameter list parsing mess from
    a3fc543459
    a715d7143d
    (some coffee might help, next time ;)
  - introduce TOK_PPSTR - to have character constants as
    written in the file (similar to TOK_PPNUM)
  - allow '\' appear in macros
  - new functions begin/end_macro to:
      - fix switching macro levels during expansion
      - allow unget_tok to unget more than one tok
  - slight speedup by using bitflags in isidnum_table

Also:
  - x86_64.c : fix decl after statements
  - i386-gen,c : fix a vstack leak with VLA on windows
  - configure/Makefile : build on windows (MSYS) was broken
  - tcc_warning: fflush stderr to keep output order (win32)
This commit is contained in:
grischka
2015-05-09 14:29:39 +02:00
parent 70a6c4601e
commit 30df3189b1
49 changed files with 1060 additions and 988 deletions

View File

@ -59,7 +59,7 @@ ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop;
ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop;
ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
@ -68,7 +68,7 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;
ST_DATA const char *funcname;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
@ -118,6 +118,12 @@ ST_FUNC void test_lvalue(void)
expect("lvalue");
}
ST_FUNC void check_vstack(void)
{
if (pvtop != vtop)
tcc_error("internal compiler error: vstack leak (%d)", vtop - pvtop);
}
/* ------------------------------------------------------------------------- */
/* symbol allocator */
static Sym *__sym_malloc(void)
@ -4005,9 +4011,9 @@ ST_FUNC void unary(void)
break;
}
case TOK___va_arg: {
CType type;
if (nocode_wanted)
tcc_error("statement in global scope");
CType type;
next();
skip('(');
expr_eq();
@ -5777,7 +5783,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
/* compute size */
save_parse_state(&saved_parse_state);
macro_ptr = init_str.str;
begin_macro(&init_str, 0);
next();
decl_initializer(type, NULL, 0, 1, 1);
/* prepare second initializer parsing */
@ -5937,7 +5943,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
decl_initializer(type, sec, addr, 1, 0);
/* restore parse state if needed */
if (init_str.str) {
tok_str_free(init_str.str);
end_macro();
restore_parse_state(&saved_parse_state);
}
/* patch flexible array member size back to -1, */
@ -6018,6 +6024,7 @@ static void func_decl_list(Sym *func_sym)
static void gen_function(Sym *sym)
{
int saved_nocode_wanted = nocode_wanted;
nocode_wanted = 0;
ind = cur_text_section->data_offset;
/* NOTE: we patch the symbol size later */
@ -6034,11 +6041,9 @@ static void gen_function(Sym *sym)
sym_push2(&local_stack, SYM_FIELD, 0, 0);
gfunc_prolog(&sym->type);
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& !strcmp(get_tok_str(sym->v, NULL), "main")) {
if (tcc_state->do_bounds_check && !strcmp(funcname, "main")) {
int i;
sym = local_stack;
Sym *sym;
for (i = 0, sym = local_stack; i < 2; i++, sym = sym->prev) {
if (sym->v & SYM_FIELD || sym->prev->v & SYM_FIELD)
break;
@ -6075,14 +6080,16 @@ static void gen_function(Sym *sym)
func_var = 0; /* for safety */
ind = 0; /* for safety */
nocode_wanted = saved_nocode_wanted;
check_vstack();
}
ST_FUNC void gen_inline_functions(void)
{
Sym *sym;
int *str, inline_generated, i;
int inline_generated, i, ln;
struct InlineFunc *fn;
ln = file->line_num;
/* iterate while inline function are referenced */
for(;;) {
inline_generated = 0;
@ -6092,18 +6099,17 @@ ST_FUNC void gen_inline_functions(void)
if (sym && sym->c) {
/* the function was used: generate its code and
convert it to a normal function */
str = fn->token_str;
fn->sym = NULL;
if (file)
pstrcpy(file->filename, sizeof file->filename, fn->filename);
sym->r = VT_SYM | VT_CONST;
sym->type.t &= ~VT_INLINE;
macro_ptr = str;
begin_macro(&fn->func_str, 0);
next();
cur_text_section = text_section;
gen_function(sym);
macro_ptr = NULL; /* fail safe */
end_macro();
inline_generated = 1;
}
@ -6111,10 +6117,12 @@ ST_FUNC void gen_inline_functions(void)
if (!inline_generated)
break;
}
file->line_num = ln;
/* free tokens of unused inline functions */
for (i = 0; i < tcc_state->nb_inline_fns; ++i) {
fn = tcc_state->inline_fns[i];
str = fn->token_str;
tok_str_free(str);
if (fn->sym)
tok_str_free(fn->func_str.str);
}
dynarray_reset(&tcc_state->inline_fns, &tcc_state->nb_inline_fns);
}
@ -6267,19 +6275,22 @@ static int decl0(int l, int is_for_loop_init)
the compilation unit only if they are used */
if ((type.t & (VT_INLINE | VT_STATIC)) ==
(VT_INLINE | VT_STATIC)) {
TokenString func_str;
int block_level;
struct InlineFunc *fn;
const char *filename;
tok_str_new(&func_str);
filename = file ? file->filename : "";
fn = tcc_malloc(sizeof *fn + strlen(filename));
strcpy(fn->filename, filename);
fn->sym = sym;
tok_str_new(&fn->func_str);
block_level = 0;
for(;;) {
int t;
if (tok == TOK_EOF)
tcc_error("unexpected end of file");
tok_str_add_tok(&func_str);
tok_str_add_tok(&fn->func_str);
t = tok;
next();
if (t == '{') {
@ -6290,13 +6301,8 @@ static int decl0(int l, int is_for_loop_init)
break;
}
}
tok_str_add(&func_str, -1);
tok_str_add(&func_str, 0);
filename = file ? file->filename : "";
fn = tcc_malloc(sizeof *fn + strlen(filename));
strcpy(fn->filename, filename);
fn->sym = sym;
fn->token_str = func_str.str;
tok_str_add(&fn->func_str, -1);
tok_str_add(&fn->func_str, 0);
dynarray_add((void ***)&tcc_state->inline_fns, &tcc_state->nb_inline_fns, fn);
} else {