From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 13E353857C53; Sat, 17 Jul 2021 14:29:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 13E353857C53 From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/101488] Implement p1042r1 __VA_OPT__ placemarker changes Date: Sat, 17 Jul 2021 14:29:51 +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: Sat, 17 Jul 2021 14:29:52 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D101488 --- Comment #1 from Jakub Jelinek --- I've tried a WIP (with just 0 && or commenting out parts of current code instead of removing/cleaning up) that attempts to treat __VA_OPT__ ( ... ) = with ## before __VA_OPT__ and/or after ) more similarly to the case where the __VA_OPT__, ( and ) tokens are missing: --- libcpp/macro.c.jj 2021-07-16 11:10:08.512925510 +0200 +++ libcpp/macro.c 2021-07-17 15:55:03.178568895 +0200 @@ -2059,7 +2059,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 +2184,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; } } @@ -2197,7 +2197,7 @@ replace_args (cpp_reader *pfile, cpp_has MACRO_ARG_TOKEN_EXPANDED, arg, arg->expanded); - if (last_token_is (buff, vaopt_start)) + if (0 && last_token_is (buff, vaopt_start)) { /* We're expanding an arg at the beginning of __VA_OPT__. Skip padding. */ @@ -2215,7 +2215,7 @@ 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)) + /* && !last_token_is (buff, vaopt_start) */) { const cpp_token *t =3D padding_token (pfile, src); unsigned index =3D expanded_token_index (pfile, macro, src, i); @@ -2301,7 +2301,7 @@ replace_args (cpp_reader *pfile, cpp_has /* 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)) + /*&& !last_token_is (buff, vaopt_start)*/) { const cpp_token *t =3D &pfile->avoid_paste; tokens_buff_add_token (buff, virt_locs, @@ -3544,6 +3544,8 @@ create_iso_definition (cpp_reader *pfile bool varadic =3D false; bool ok =3D false; cpp_macro *macro =3D NULL; + bool vaopt_after_paste =3D false; + unsigned int vaopt_end_idx =3D 0; /* Look at the first token, to see if this is a function-like macro. */ @@ -3700,14 +3702,33 @@ create_iso_definition (cpp_reader *pfile token[-1].flags |=3D SP_DIGRAPH; if (token->flags & PREV_WHITE) token[-1].flags |=3D SP_PREV_WHITE; + if (macro->count =3D=3D vaopt_end_idx) + token[-2].flags |=3D PASTE_LEFT; } following_paste_op =3D true; } else following_paste_op =3D false; - if (vaopt_tracker.update (token) =3D=3D vaopt_state::ERROR) + vaopt_state::update_type vostate =3D vaopt_tracker.update (token); + if (vostate =3D=3D vaopt_state::INCLUDE) + continue; + if (vostate =3D=3D vaopt_state::ERROR) goto out; + if (vostate =3D=3D vaopt_state::BEGIN + && macro->count > 1 + && (token[-1].flags & PASTE_LEFT)) + vaopt_after_paste =3D true; + if (vostate =3D=3D vaopt_state::DROP && vaopt_after_paste) + { + vaopt_after_paste =3D false; + /* Duplicate the PASTE_LEFT flag on ( after __VA_OPT__ + if ## is before __VA_OPT__. */ + if (!vaopt_tracker.stringify ()) + token->flags |=3D PASTE_LEFT; + } + if (vostate =3D=3D vaopt_state::END) + vaopt_end_idx =3D macro->count; } /* We're committed to winning now. */ and that results into identical output on the #c0 testcase above as clang++, and ditto macro_vaopt_p1042r1.cpp testcase, but macro_vaopt_expand.cpp diff= ers slightly: -9: HT_A() C ( ) B ( ) "A()" +9: TONG C ( ) B ( ) "A()" -27_1: BA0 11 +27_1: BexpandedA0 11 (- is gcc with #__VA_OPT__ and the above patch, + is clang++). That actual= ly matches how the F0 case in #define LPAREN (=20 #define A0 expandedA0 #define A1 expandedA1 A0 #define A2 expandedA2 A1 #define A3 expandedA3 A2 #define A() B LPAREN ) #define B() C LPAREN ) #define C() D LPAREN ) #define HT_B() TONG #define F0(x, ...) HT_ ## x x A() #x #define F(x, ...) HT_ ## __VA_OPT__(x x A() #x) 8: F0(A(),1) 9: F(A(),1) is handled, so I'm getting lost on what is supposed to be special about __VA_OPT__ here. In any case, the unpatched libcpp handled that F0 and F c= ases the same as clang++. And we probably need more extensive testsuite coverag= e...=