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

Reply via email to