On 7/3/26 1:25 PM, Vladislav Semykin wrote:
Yes, I missed this out, thanks for the advice! There is no information about gcc-verify and gcc-style in https://gcc.gnu.org/contribute.html, or I didn't see this. Thanks to the distributed GCC team to make this so
convenient and simple to check. I will always check my changes with them before 
mail to [email protected]

Indeed, the information about those aliases is in /gitwrite.html, it should move to /git.html at least.

I kept glvalue_p because [expr.typeid]/4 applies only to a glvalue of 
polymorphic
class type; everything else is unevaluated per /5. In our frontend, class 
prvalues
are not glvalues (glvalue_p is false for clk_class), which matters when
resolves_to_fixed_type_p is still false - e.g. typeid (ok = false, D()) in
g++.dg/cpp2a/constexpr-typeid2.C, where the test explicitly says "Not a glvalue"
and expects no evaluation. Without the glvalue check we'd take the evaluated 
re-parse path there.

Aha, that seems like a bug in resolves_to_fixed_type_p, that it doesn't handle COMPOUND_EXPR. So go ahead and keep the glvalue_p, but add a comment that it's only necessary because resolves_to_fixed_type_p isn't always right.

@@ -8570,9 +8571,29 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
        else
          {
            tree expression;
+           /* [expr.typeid]/4-5: parse the operand unevaluated first; if it is
+              a polymorphic glvalue, roll back and re-parse it evaluated,
+              since an evaluated parse has irreversible side-effects
+              (mark_used -> instantiation; lambda capture).  */
+           cp_lexer_save_tokens (parser->lexer);
+           {
+             cp_unevaluated u;
+             expression = cp_parser_expression (parser, &idk);
+           }
+           if (expression != error_mark_node
+               && processing_template_decl == 0
+               && typeid_evaluated_p (expression))
+             {
+               /* Re-parse the operand evaluated so the /4 side-effects occur.
+                  The unevaluated pass above called no mark_used and captured
+                  nothing, so rolling back has nothing to undo.  */
+               cp_lexer_rollback_tokens (parser->lexer);
+               cp_evaluated ev;

You don't need (or want) cp_evaluated here; this shouldn't override the typeid itself being within an unevaluated operand.

@@ -23003,8 +23003,24 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
          }
        else
          {
-           operand_0 = RECUR (operand_0);
-           RETURN (build_typeid (operand_0, complain));
+           /* [expr.typeid]/4-5: substitute the operand unevaluated first, then
+              again evaluated if it is a polymorphic glvalue, so the /4
+              side-effects occur.  The unevaluated pass instantiates nothing,
+              so re-substituting has nothing to undo (PR c++/125886).  */
+           tree operand;
+           tree uneval;
+             {
+               cp_unevaluated u;
+               uneval = RECUR (operand_0);
+             }
+           if (typeid_evaluated_p (uneval))
+             {
+               cp_evaluated ev;

Likewise.

Jason

Reply via email to