On Wed, Jun 24, 2026 at 11:00:39PM +0300, Vladislav Semykin wrote: > > From 9b1d5ef0c5ad93636bbf1dc22c6007b7d935e44c Mon Sep 17 00:00:00 2001 > From: Vladislav Semykin <[email protected]> > Date: Wed, 24 Jun 2026 22:47:58 +0300 > Subject: [PATCH] cp: fix unevaluated operand context for typeid > > PR c++/125886 - std::declval in unevaluated typeid operand incorrectly > triggers __declval_protector > > PR c++/125886 > PR 125886
Only the first PR line should be here. > gcc/cp/ChangeLog: > > * cp-tree.h (cp_unevaluated_operand): Mention typeid in comment. > * parser.cc (cp_parser_postfix_expression): Set cp_unevaluated_operand > and c_inhibit_evaluation_warnings before parsing typeid expression operand. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/pr125886.C: New test. > > Signed-off-by: Vladislav Semykin <[email protected]> > --- > gcc/cp/cp-tree.h | 5 +++-- > gcc/cp/parser.cc | 5 +++++ > gcc/testsuite/g++.dg/cpp0x/pr125886.C | 8 ++++++++ > 3 files changed, 16 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr125886.C > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index 132139f9d..25021c62d 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -6339,8 +6339,9 @@ extern bool comparing_contracts; > 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, typeof, alignof, or typeid (when the operand is not > + of polymorphic class type). This is a count since operands > + to sizeof can be nested. */ > > extern int cp_unevaluated_operand; > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index 8194106c6..d426ff655 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -8571,8 +8571,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool > address_p, bool cast_p, > { > tree expression; > > + /* As for sizeof and noexcept before parsing. */ > + ++cp_unevaluated_operand; > + ++c_inhibit_evaluation_warnings; > /* Look for an expression. */ > expression = cp_parser_expression (parser, & idk); > + --cp_unevaluated_operand; > + --c_inhibit_evaluation_warnings; Unfortunately this doesn't look correct: as per [expr.typeid], only typeid applied to a non-polymorphic expression is unevaluated. When the operand is a glvalue of polymorphic class type, it is evaluated. This test should still emit an error: class A { virtual ~A(); }; void foo() { char const *a = typeid(std::declval<A>()).name(); } I haven't tried it but we may have to parse the operand twice: first as an unevaluated operand and, in case of a polymorphic class type, a second time, this time as evaluated operand. But at this point it's just my guess. > /* Compute its typeid. */ > postfix_expression = build_typeid (expression, tf_warning_or_error); > /* Look for the `)' token. */ > diff --git a/gcc/testsuite/g++.dg/cpp0x/pr125886.C > b/gcc/testsuite/g++.dg/cpp0x/pr125886.C > new file mode 100644 > index 000000000..70db1e89e > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/pr125886.C > @@ -0,0 +1,8 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=c++11" } */ > + > +#include <typeinfo> > +#include <utility> > + > +class A {}; > +void foo() { char const *a = typeid(std::declval<A>()).name(); } > -- > 2.43.0 > Marek
