[Bug c++/101488] Implement p1042r1 __VA_OPT__ placemarker changes
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Jul 19 12:51:40 GMT 2021
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101488
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Different patch:
--- libcpp/macro.c.jj 2021-07-16 11:10:08.512925510 +0200
+++ libcpp/macro.c 2021-07-19 14:19:48.217122675 +0200
@@ -236,10 +236,20 @@ class vaopt_state {
return m_state == 0;
}
+ /* Return true for # __VA_OPT__. */
bool stringify () const
{
return m_stringify;
- }
+ }
+
+ /* Return true if inside of __VA_OPT__ args but not inside of extra ()s
+ nested in it, i.e. when if next token is ), it will be END.
+ Next token is guaranteed to appear, as otherwise it would be ERROR
+ earlier. */
+ bool maybe_before_end () const
+ {
+ return m_state == 3;
+ }
private:
@@ -2025,6 +2035,7 @@ replace_args (cpp_reader *pfile, cpp_has
i = 0;
vaopt_state vaopt_tracker (pfile, macro->variadic, &args[macro->paramc -
1]);
const cpp_token **vaopt_start = NULL;
+ bool vaopt_paste_left = false;
for (src = macro->exp.tokens; src < limit; src++)
{
unsigned int arg_tokens_count;
@@ -2050,6 +2061,8 @@ replace_args (cpp_reader *pfile, cpp_has
t->src_loc, t->src_loc,
map, index);
}
+ vaopt_paste_left = (src != macro->exp.tokens
+ && (src[-1].flags & PASTE_LEFT));
vaopt_start = tokens_buff_last_token_ptr (buff);
}
else if (vostate == vaopt_state::END)
@@ -2059,7 +2072,7 @@ replace_args (cpp_reader *pfile, cpp_has
/* Remove any tail padding from inside the __VA_OPT__. */
paste_flag = tokens_buff_last_token_ptr (buff);
- while (paste_flag && paste_flag != start
+ while (0 && paste_flag && paste_flag != start
&& (*paste_flag)->type == CPP_PADDING)
{
tokens_buff_remove_last_token (buff);
@@ -2184,7 +2197,7 @@ replace_args (cpp_reader *pfile, cpp_has
previous emitted token is at the beginning of __VA_OPT__;
placemarkers within __VA_OPT__ are ignored in that case. */
else if (arg_tokens_count == 0
- && tmp_token_ptr != vaopt_start)
+/* && tmp_token_ptr != vaopt_start */)
paste_flag = tmp_token_ptr;
}
}
@@ -2214,8 +2227,9 @@ replace_args (cpp_reader *pfile, cpp_has
/* Padding on the left of an argument (unless RHS of ##). */
if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
- && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT)
- && !last_token_is (buff, vaopt_start))
+ && src != macro->exp.tokens
+ && !(src[-1].flags & PASTE_LEFT)
+ && (!last_token_is (buff, vaopt_start) || !vaopt_paste_left))
{
const cpp_token *t = padding_token (pfile, src);
unsigned index = expanded_token_index (pfile, macro, src, i);
@@ -2300,8 +2314,12 @@ replace_args (cpp_reader *pfile, cpp_has
NODE_NAME (node), src->val.macro_arg.arg_no);
/* Avoid paste on RHS (even case count == 0). */
- if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)
- && !last_token_is (buff, vaopt_start))
+ if (!pfile->state.in_directive
+ && !(src->flags & PASTE_LEFT)
+ && (!vaopt_tracker.maybe_before_end ()
+ || src[1].type != CPP_CLOSE_PAREN
+ || (src[1].flags & PASTE_LEFT) == 0)
+ /*&& !last_token_is (buff, vaopt_start)*/)
{
const cpp_token *t = &pfile->avoid_paste;
tokens_buff_add_token (buff, virt_locs,
With this one, clang's macro_vaopt_expand.cpp and macro_vaopt_p1042r1.cpp and
the #c0 testcase preprocess the same between g++ and clang++, but
c-c++-common/cpp/va-opt-3.c has one difference:
t26 f20 (f21 (), 2);
/* { dg-final { scan-file va-opt-3.i "t26 f17 h;" } } */
which yields with the patched cc1plus into
t26 f17 f17 m4();
I guess I understand why for the cases of x ## __VA_OPT__ (y z) and __VA_OPT__
(a b) ## c we want
for y and b macros use MACRO_ARG_TOKEN_EXPANDED instead of
MACRO_ARG_TOKEN_NORMAL when it would be
x ## y z or a b ## c, but already in the above patch I had to uncomment again
the
if (last_token_is (buff, vaopt_start))
{
/* We're expanding an arg at the beginning of __VA_OPT__.
Skip padding. */
while (arg_tokens_count)
{
const cpp_token *t = macro_arg_token_iter_get_token (&from);
if (t->type != CPP_PADDING)
break;
macro_arg_token_iter_forward (&from);
--arg_tokens_count;
}
}
padding token removal because otherwise e.g. the #c1 testcase (and
macro_vaopt_expand.cpp) misbehaves - MACRO_ARG_TOKEN_EXPANDED
tokens for the x macro start with CPP_PADDING and at least if clang++ is
correct we don't want it there.
The question is if we should optimize away a single CPP_PADDING tokens or
unlimited number of them, whether it is possible
that somehow the macro expanded definition would start with multiple
CPP_PADDING tokens and whether some of them shouldn't be kept.
For the t26 case, we need to remove some trailing CPP_PADDING tokens too, but
as various testcases show, not all of them.
So, perhaps remember in the loop in some integer variable how many CPP_PADDING
tokens should be removed if next token would be vaopt_state::END
with PASTE_LEFT on it?
More information about the Gcc-bugs
mailing list