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

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;
 	    /* 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

Reply via email to