mirror of
https://github.com/frida/tinycc
synced 2025-01-03 02:24:24 +03:00
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).
This commit is contained in:
parent
3db037387c
commit
3e77bfb6e9
1
tcc.h
1
tcc.h
@ -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 */
|
||||
|
15
tccpp.c
15
tccpp.c
@ -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;
|
||||
|
14
tests/pp/17.c
Normal file
14
tests/pp/17.c
Normal file
@ -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));
|
6
tests/pp/17.expect
Normal file
6
tests/pp/17.expect
Normal file
@ -0,0 +1,6 @@
|
||||
X162 "onetok"
|
||||
X161 "onetok"
|
||||
X163 "one##tok"
|
||||
X170 x ## y
|
||||
X171 x ## y
|
||||
X180 return Z(Z(1));
|
Loading…
Reference in New Issue
Block a user