Message ID | 20211230092409.GX2646553@tucnak |
---|---|
State | New |
Headers | show |
Series | libcpp: Fix up ##__VA_OPT__ handling [PR89971] | expand |
On 12/30/2021 2:24 AM, Jakub Jelinek via Gcc-patches wrote: > Hi! > > In the following testcase we incorrectly error about pasting / token > with padding token (which is a result of __VA_OPT__); instead we should > like e.g. for ##arg where arg is empty macro argument clear PASTE_LEFT > flag of the previous token if __VA_OPT__ doesn't add any real tokens > (which can happen either because the macro doesn't have any tokens > passed to ... (i.e. __VA_ARGS__ expands to empty) or when __VA_OPT__ > doesn't have any tokens in between ()s). > > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok > for trunk? > > 2021-12-30 Jakub Jelinek <jakub@redhat.com> > > PR preprocessor/89971 > libcpp/ > * macro.c (replace_args): For ##__VA_OPT__, if __VA_OPT__ expands > to no tokens at all, drop PASTE_LEFT flag from the previous token. > gcc/testsuite/ > * c-c++-common/cpp/va-opt-9.c: New test. OK jeff
--- libcpp/macro.c.jj 2021-12-01 10:07:46.774663941 +0100 +++ libcpp/macro.c 2021-12-29 15:22:09.393455799 +0100 @@ -2094,8 +2094,14 @@ replace_args (cpp_reader *pfile, cpp_has tokens_buff_add_token (buff, virt_locs, t, t->src_loc, t->src_loc, NULL, 0); + continue; } - else if (src->flags & PASTE_LEFT) + if (start && paste_flag == start && (*start)->flags & PASTE_LEFT) + /* If __VA_OPT__ expands to nothing (either because __VA_ARGS__ + is empty or because it is __VA_OPT__() ), drop PASTE_LEFT + flag from previous token. */ + copy_paste_flag (pfile, start, &pfile->avoid_paste); + if (src->flags & PASTE_LEFT) { /* Don't avoid paste after all. */ while (paste_flag && paste_flag != start --- gcc/testsuite/c-c++-common/cpp/va-opt-9.c.jj 2021-12-29 15:30:48.231203467 +0100 +++ gcc/testsuite/c-c++-common/cpp/va-opt-9.c 2021-12-29 15:40:12.676317163 +0100 @@ -0,0 +1,20 @@ +/* PR preprocessor/89971 */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99" { target c } } */ +/* { dg-options "-std=c++20" { target c++ } } */ + +int a, c; +#define m1(...) a /##__VA_OPT__(b) c +#define m2(...) a /##__VA_OPT__() c +#define m3(...) a##__VA_OPT__()##b = 1 +#define m4(...) a##__VA_OPT__(b c d)##e = 2 + +int +foo (void) +{ + int d = m1(); + int e = m2(1); + int m3(1 2 3); + int m4(); + return d + e + ab + ae; +}