From 75c6695932b55b914f16b20dc32ff3ef1203ed4b Mon Sep 17 00:00:00 2001 From: Joe Soroka Date: Tue, 1 Feb 2011 13:23:40 -0800 Subject: [PATCH] tccpp: fix bug in handling of recursive macros --- tcc.h | 1 + tccpp.c | 17 +++++++++++++++-- tests/tcctest.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/tcc.h b/tcc.h index 7d426073..a3a9c78a 100644 --- a/tcc.h +++ b/tcc.h @@ -683,6 +683,7 @@ struct TCCState { #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 */ #define TOK_SAR 0x02 /* signed shift right */ diff --git a/tccpp.c b/tccpp.c index c461ff87..27f9870c 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2797,7 +2797,8 @@ static inline int *macro_twosharps(const int *macro_str) if (tok == TOK_TWOSHARPS) continue; while (*ptr == TOK_TWOSHARPS) { - t = *++ptr; + do { t = *++ptr; } while (t == TOK_NOSUBST); + if (t && t != TOK_TWOSHARPS) { TOK_GET(&t, &ptr, &cval); @@ -2856,11 +2857,20 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, TOK_GET(&t, &ptr, &cval); if (t == 0) break; + if (t == TOK_NOSUBST) { + /* following token has already been subst'd. just copy it on */ + tok_str_add2(tok_str, TOK_NOSUBST, NULL); + TOK_GET(&t, &ptr, &cval); + goto no_subst; + } s = define_find(t); if (s != NULL) { /* if nested substitution, do nothing */ - if (sym_find2(*nested_list, t)) + if (sym_find2(*nested_list, t)) { + /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */ + tok_str_add2(tok_str, TOK_NOSUBST, NULL); goto no_subst; + } ml.p = macro_ptr; if (can_read_stream) ml.prev = *can_read_stream, *can_read_stream = &ml; @@ -2928,6 +2938,9 @@ ST_FUNC void next(void) macro_ptr = NULL; } goto redo; + } else if (tok == TOK_NOSUBST) { + /* discard preprocessor's nosubst markers */ + goto redo; } } diff --git a/tests/tcctest.c b/tests/tcctest.c index 01289575..f62983d4 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -45,6 +45,7 @@ void string_test(); void expr_test(); void macro_test(); +void recursive_macro_test(); void scope_test(); void forward_test(); void funcptr_test(); @@ -281,6 +282,35 @@ comment TEST2(); } + +static void print_num(char *fn, int line, int num) { + printf("fn %s, line %d, num %d\n", fn, line, num); +} + +void recursive_macro_test(void) +{ +#if 0 /* doesnt work yet */ +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) +#define STB_WEAK 2 /* Weak symbol */ +#define ELFW(type) ELF##32##_##type + printf("%d\n", ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(123))); +#endif + +#define WRAP(x) x + +#define print_num(x) print_num(__FILE__,__LINE__,x) + print_num(123); + WRAP(print_num(123)); + WRAP(WRAP(print_num(123))); + +static struct recursive_macro { int rm_field; } G; +#define rm_field (G.rm_field) + printf("rm_field = %d\n", rm_field); + printf("rm_field = %d\n", WRAP(rm_field)); + WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field)))); +} + int op(a,b) { return a / b; @@ -501,6 +531,7 @@ int main(int argc, char **argv) string_test(); expr_test(); macro_test(); + recursive_macro_test(); scope_test(); forward_test(); funcptr_test(); -- 2.11.4.GIT