From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 0D4C838515FC; Mon, 19 Jul 2021 12:51:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0D4C838515FC From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/101488] Implement p1042r1 __VA_OPT__ placemarker changes Date: Mon, 19 Jul 2021 12:51:40 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 12.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Jul 2021 12:51:41 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D101488 --- Comment #2 from Jakub Jelinek --- 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 =3D=3D 0; } + /* Return true for # __VA_OPT__. */ bool stringify () const { return m_stringify; - }=20=20 + } + + /* 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 =3D=3D 3; + } private: @@ -2025,6 +2035,7 @@ replace_args (cpp_reader *pfile, cpp_has i =3D 0; vaopt_state vaopt_tracker (pfile, macro->variadic, &args[macro->paramc - 1]); const cpp_token **vaopt_start =3D NULL; + bool vaopt_paste_left =3D false; for (src =3D 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 =3D (src !=3D macro->exp.tokens + && (src[-1].flags & PASTE_LEFT)); vaopt_start =3D tokens_buff_last_token_ptr (buff); } else if (vostate =3D=3D 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 =3D tokens_buff_last_token_ptr (buff); - while (paste_flag && paste_flag !=3D start + while (0 && paste_flag && paste_flag !=3D start && (*paste_flag)->type =3D=3D 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 =3D=3D 0 - && tmp_token_ptr !=3D vaopt_start) +/* && tmp_token_ptr !=3D vaopt_start */) paste_flag =3D 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_padd= ing) - && src !=3D macro->exp.tokens && !(src[-1].flags & PASTE_LEFT) - && !last_token_is (buff, vaopt_start)) + && src !=3D macro->exp.tokens + && !(src[-1].flags & PASTE_LEFT) + && (!last_token_is (buff, vaopt_start) || !vaopt_paste_left)) { const cpp_token *t =3D padding_token (pfile, src); unsigned index =3D 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 =3D=3D 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 !=3D CPP_CLOSE_PAREN + || (src[1].flags & PASTE_LEFT) =3D=3D 0) + /*&& !last_token_is (buff, vaopt_start)*/) { const cpp_token *t =3D &pfile->avoid_paste; tokens_buff_add_token (buff, virt_locs, With this one, clang's macro_vaopt_expand.cpp and macro_vaopt_p1042r1.cpp a= nd 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_OP= T__ (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 aga= in 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 =3D macro_arg_token_iter_get_token (&f= rom); if (t->type !=3D 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, b= ut as various testcases show, not all of them. So, perhaps remember in the loop in some integer variable how many CPP_PADD= ING tokens should be removed if next token would be vaopt_state::END with PASTE_LEFT on it?=