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