https://gcc.gnu.org/g:0aca4be8913d4aee1adda2e49e971afffdf03f61

commit r16-8879-g0aca4be8913d4aee1adda2e49e971afffdf03f61
Author: Marek Polacek <[email protected]>
Date:   Thu May 7 09:51:53 2026 -0400

    c++/reflection: ICE with bases_of [PR125206]
    
    Here we crash in strip_typedefs_expr because we recurse on a
    REFLECT_EXPR with TREE_BINFO as its operand, which is not a code this
    function handles.  It seems to me that we don't need to recurse for
    REFLECT_EXPRs at all.  Alternatively, we could just handle TREE_BINFO.
    
            PR c++/125206
    
    gcc/cp/ChangeLog:
    
            * tree.cc (strip_typedefs_expr) <case REFLECT_EXPR>: Always
            return instead of recursing.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/reflect/bases_of4.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>
    (cherry picked from commit 694d048d87457e7728b9b5484a9b97cb0e617e40)

Diff:
---
 gcc/cp/tree.cc                           |  7 ++---
 gcc/testsuite/g++.dg/reflect/bases_of4.C | 45 ++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 26e12f848c61..8f6ba3420624 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2153,12 +2153,9 @@ strip_typedefs_expr (tree t, bool *remove_attributes, 
unsigned int flags)
 
     case LAMBDA_EXPR:
     case STMT_EXPR:
-      return t;
-
+    /* ^^alias represents the alias itself, not the underlying type.  */
     case REFLECT_EXPR:
-      /* ^^alias represents the alias itself, not the underlying type.  */
-      if (TYPE_P (REFLECT_EXPR_HANDLE (t)))
-       return t;
+      return t;
 
     default:
       break;
diff --git a/gcc/testsuite/g++.dg/reflect/bases_of4.C 
b/gcc/testsuite/g++.dg/reflect/bases_of4.C
new file mode 100644
index 000000000000..843f0e53c4e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/bases_of4.C
@@ -0,0 +1,45 @@
+// PR c++/125206
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+#include <type_traits>
+
+template<auto...> struct mp_list_v
+{
+};
+
+template<class...> struct mp_list
+{
+};
+
+template<auto V> using mp_value = std::integral_constant<decltype(V), V>;
+
+template<class L, template<class...> class B> struct mp_rename_impl;
+
+template<template<class...> class L, class... T, template<class...> class B> 
struct mp_rename_impl<L<T...>, B>
+{
+    using type = B<T...>;
+};
+
+template<template<auto...> class L, auto... A, template<class...> class B> 
struct mp_rename_impl<L<A...>, B>
+{
+    using type = B<mp_value<A>...>;
+};
+
+template<class L, template<class...> class B> using mp_rename = typename 
mp_rename_impl<L, B>::type;
+
+class X1
+{
+};
+
+class Z: public X1
+{
+};
+
+int main()
+{
+    constexpr auto all = std::meta::access_context::unchecked();
+    constexpr auto L1 = ^^mp_list_v< bases_of(^^Z, all)[0] >;
+    using L2 = mp_rename<typename [: L1 :], mp_list>;
+}

Reply via email to