diff options
| author | Michael Matz <matz@suse.de> | 2016-10-31 03:59:31 +0100 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-15 17:49:56 +0100 |
| commit | 3e77bfb6e9b286bbb53377fb5d7343e58ba34127 (patch) | |
| tree | f8798307b10322c629c01217dafb36b3ab013a84 | |
| parent | 3db037387c16c7e582f76167d32d5c29ac32fb15 (diff) | |
| download | tinycc-3e77bfb6e9b286bbb53377fb5d7343e58ba34127.tar.gz tinycc-3e77bfb6e9b286bbb53377fb5d7343e58ba34127.tar.bz2 | |
tccpp: Fix token pasting
See testcase. We must always paste tokens (at least if not
currently substing a normal argument, which is a speed optimization
only now) but at the same time must not regard a ## token
coming from argument expansion as the token-paste operator, nor
if we constructed a ## token due to pasting itself (that was already
checked by pp/01.c).
| -rw-r--r-- | tcc.h | 1 | ||||
| -rw-r--r-- | tccpp.c | 15 | ||||
| -rw-r--r-- | tests/pp/17.c | 14 | ||||
| -rw-r--r-- | tests/pp/17.expect | 6 |
4 files changed, 29 insertions, 7 deletions
@@ -899,6 +899,7 @@ struct filespec { #define TOK_TWOSHARPS 0xca /* ## preprocessing token */ #define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */ #define TOK_NOSUBST 0xcc /* means following token has already been pp'd */ +#define TOK_PPJOIN 0xce /* A '##' in the right position to mean pasting */ #define TOK_SHL 0x01 /* shift left */ #define TOK_SAR 0x02 /* signed shift right */ @@ -1508,6 +1508,7 @@ ST_FUNC void parse_define(void) if (1 == spc) --tokstr_buf.len; spc = 3; + tok = TOK_PPJOIN; } else if ('#' == tok) { spc = 4; } else if (check_space(tok, &spc)) { @@ -2958,10 +2959,10 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) int l0 = str.len; st = s->d; /* if '##' is present before or after, no arg substitution */ - if (*macro_str == TOK_TWOSHARPS || t1 == TOK_TWOSHARPS) { + if (*macro_str == TOK_PPJOIN || t1 == TOK_PPJOIN) { /* special case for var arg macros : ## eats the ',' if empty VA_ARGS variable. */ - if (t1 == TOK_TWOSHARPS && t0 == ',' && gnu_ext && s->type.t) { + if (t1 == TOK_PPJOIN && t0 == ',' && gnu_ext && s->type.t) { if (*st == 0) { /* suppress ',' '##' */ str.len -= 2; @@ -3277,7 +3278,7 @@ static inline int *macro_twosharps(const int *ptr0) /* we search the first '##' */ for (ptr = ptr0;;) { TOK_GET(&t, &ptr, &cval); - if (t == TOK_TWOSHARPS) + if (t == TOK_PPJOIN) break; if (t == 0) return NULL; @@ -3290,9 +3291,9 @@ static inline int *macro_twosharps(const int *ptr0) TOK_GET(&t, &ptr, &cval); if (t == 0) break; - if (t == TOK_TWOSHARPS) + if (t == TOK_PPJOIN) continue; - while (*ptr == TOK_TWOSHARPS) { + while (*ptr == TOK_PPJOIN) { int t1; CValue cv1; /* given 'a##b', remove nosubsts preceding 'a' */ if (start_of_nosubsts >= 0) @@ -3300,7 +3301,7 @@ static inline int *macro_twosharps(const int *ptr0) /* given 'a##b', remove nosubsts preceding 'b' */ while ((t1 = *++ptr) == TOK_NOSUBST) ; - if (t1 && t1 != TOK_TWOSHARPS) { + if (t1 && t1 != TOK_PPJOIN) { TOK_GET(&t1, &ptr, &cv1); if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) { if (paste_tokens(t, &cval, t1, &cv1)) { @@ -3346,7 +3347,7 @@ static void macro_subst( spc = nosubst = 0; /* first scan for '##' operator handling */ - if (can_read_stream & 1) { + if (can_read_stream) { macro_str1 = macro_twosharps(ptr); if (macro_str1) ptr = macro_str1; diff --git a/tests/pp/17.c b/tests/pp/17.c new file mode 100644 index 0000000..f12196f --- /dev/null +++ b/tests/pp/17.c @@ -0,0 +1,14 @@ +#define STR1(u) # u +#define pass(a) a +#define __ASM_REG(reg) STR1(one##reg) +#define _ASM_DX __ASM_REG(tok) +X162 pass(__ASM_REG(tok)) +X161 pass(_ASM_DX) +X163 pass(STR1(one##tok)) + +X170 pass(x ## y) +X171 pass(x pass(##) y) + +#define Y(x) Z(x) +#define X Y +X180 return X(X(1)); diff --git a/tests/pp/17.expect b/tests/pp/17.expect new file mode 100644 index 0000000..e95aafe --- /dev/null +++ b/tests/pp/17.expect @@ -0,0 +1,6 @@ +X162 "onetok" +X161 "onetok" +X163 "one##tok" +X170 x ## y +X171 x ## y +X180 return Z(Z(1)); |
