On 7/2/26 1:29 AM, Vladislav Semykin wrote:
Good day! My mistake was that I continued talking in the same previous
email thread, sorry about that.
No worries.
Changes since v2:
- Apply the same two-pass (unevaluated-then-evaluated) logic to
template-dependent operands
in tsubst_expr (TYPEID_EXPR), as Jason requested.
- Fix lambda capture: a polymorphic glvalue typeid operand inside a
lambda without a capture-default
is now correctly diagnosed as "not captured". Root cause was
typeid_evaluated_p rejecting
reference types and being gated on the "nonnull" flag, which is
unrelated to the evaluated/unevaluated decision.
- Factor the polymorphic-glvalue predicate out into a shared
typeid_evaluated_p
helper used by the parser, tsubst, and build_typeid (Jason's request
- avoids the checks
drifting out of sync).
- Drop the cxx_dialect >= cxx11 gate: per Jason, DR613 applies in all
modes,
since finish_non_static_data_member doesn't check cxx_dialect either.
- Also fixes PR c++/68604 and PR c++/116385, and removes a now-stale
xfail in
g++.dg/coroutines/unevaluated.C (PR c++/68604).
Tested full CI on: x86_64 GNU/Linux 6.17.0-35-generic Ubuntu 24.04.
FYI, these tests are broken before my changes (the full test log via
'make -C gcc -k check-c++-all' attached too):
Yes, most of these are preexisting issues.
FAIL: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11
at line 885 (test for warnings, line 884)
XPASS: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11
PR analyzer/103546 (test for bogus messages, line 892)
FAIL: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11
(test for excess errors)
FAIL: g++.dg/guality/pr55665.C -O2 -flto -fno-use-linker-plugin -flto-
partition=none line 23 p == 40
FAIL: g++.dg/modules/compile-std1.C -std=c++26 -fimplicit-constexpr
(test for excess errors)
...but this one is surprising, can you look at testsuite/g++/g++.log to
see what's breaking?
From acc669f9364264ecf93f1341e7037e916a798c6b Mon Sep 17 00:00:00 2001
From: Vladislav Semykin <[email protected]>
Date: Tue, 30 Jun 2026 19:13:14 +0300
Subject: [PATCH] c++: fix unevaluated operand context for typeid [PR125886]
Signed-off-by: Vladislav Semykin <[email protected]>
The commit message is missing both rationale and the ChangeLog entries
that your v1 patch had, as git gcc-verify would point out.
+++ b/gcc/cp/cp-tree.h
@@ -6340,7 +6340,8 @@ extern bool cp_preserve_using_decl;
/* Nonzero if we are parsing an unevaluated operand: an operand to
sizeof, typeof, or alignof. This is a count since operands to
- sizeof can be nested. */
+ sizeof can be nested. For typeid the operand is processed
+ unevaluated, then re-processed evaluated if polymorphic
([expr.typeid]/4-5). */
+++ b/gcc/cp/parser.cc
@@ -292,7 +292,9 @@ static void missing_template_diag
static FILE *cp_lexer_debug_stream;
/* Nonzero if we are parsing an unevaluated operand: an operand to
- sizeof, typeof, or alignof. */
+ sizeof, typeof, or alignof. This is a count since operands to
+ sizeof can be nested. For typeid the operand is processed
+ unevaluated, then re-processed evaluated if polymorphic
([expr.typeid]/4-5). */
These matching comments are too long, as git gcc-style points out.
git gcc-style also flags the indentation problems in parser.cc and rtti.cc.
@@ -8570,9 +8572,30 @@ 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_operand;
+ ++c_inhibit_evaluation_warnings;
+ expression = cp_parser_expression (parser, &idk);
+ --c_inhibit_evaluation_warnings;
+ --cp_unevaluated_operand;
Why not use cp_unevaluated here as in tsubst_expr?
+typeid_evaluated_p (tree exp)
+{
+ if (exp == error_mark_node)
+ return false;
+ tree t = TREE_TYPE (exp);
+ if (!t || t == error_mark_node)
+ return false;
+ if (TYPE_REF_P (t))
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) != RECORD_TYPE && TREE_CODE (t) != UNION_TYPE)
+ return false;
+ int nonnull = 0;
+ return (TYPE_POLYMORPHIC_P (t)
+ && !resolves_to_fixed_type_p (exp, &nonnull)
+ && glvalue_p (exp));
Do we need the added glvalue_p check? I would expect a prvalue to
always resolve to a fixed type.
Jason