[gcc r17-3533] c++: modules vs typeid [PR124888]

Jason Merrill via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:f1933b5ba13bb2abd1329cfb1ba9501c90f4c516

commit r17-3533-gf1933b5ba13bb2abd1329cfb1ba9501c90f4c516
Author: Jason Merrill <[email protected]>
Date:   Fri Aug 21 20:14:25 2026 -0400

    c++: modules vs typeid [PR124888]
    
    Instantiating a template from a TU which included <typeinfo> in an importing
    TU which didn't should still work.  Instead of messing with lookup in the
    other TU, let's reuse the type that we already gave the TYPEID_EXPR.
    
            PR c++/124888
    
    gcc/cp/ChangeLog:
    
            * pt.cc (tsubst_expr): Pass type to {get,build}_typeid.
            * rtti.cc (build_typeid, get_typeid): Take it.
            (type_info_ptr_type): Remove.
            (get_tinfo_ptr): Take tinfo_ptr_type instead of voidp.
            (get_tinfo_ptr_dynamic): Likewise.
            (get_void_tinfo_ptr): Pass const_ptr_type_node.
            * cp-tree.h (build_typeid, get_typeid): Adjust.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/typeid-2_a.C: New test.
            * g++.dg/modules/typeid-2_b.C: New test.

Diff:
---
 gcc/cp/cp-tree.h                          |  4 +--
 gcc/cp/pt.cc                              |  4 +--
 gcc/cp/rtti.cc                            | 53 +++++++++++++++++--------------
 gcc/testsuite/g++.dg/modules/typeid-2_a.C | 12 +++++++
 gcc/testsuite/g++.dg/modules/typeid-2_b.C | 12 +++++++
 5 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a8af4d389450..76468700fc62 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8413,10 +8413,10 @@ extern tree convert_reflect_constant_arg	(tree, tree);
 extern GTY(()) vec<tree, va_gc> *unemitted_tinfo_decls;
 
 extern void init_rtti_processing		(void);
-extern tree build_typeid			(tree, tsubst_flags_t);
+extern tree build_typeid			(tree, tsubst_flags_t, tree = NULL_TREE);
 extern tree get_tinfo_decl_direct	        (tree, tree, int);
 extern tree get_tinfo_decl			(tree);
-extern tree get_typeid				(tree, tsubst_flags_t);
+extern tree get_typeid				(tree, tsubst_flags_t, tree = NULL_TREE);
 extern tree build_headof			(tree);
 extern tree build_dynamic_cast			(location_t, tree, tree,
 						 tsubst_flags_t);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d9a002e36b74..4f7943f625f1 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23081,7 +23081,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	if (TYPE_P (operand_0))
 	  {
 	    operand_0 = tsubst (operand_0, args, complain, in_decl);
-	    RETURN (get_typeid (operand_0, complain));
+	    RETURN (get_typeid (operand_0, complain, TREE_TYPE (t)));
 	  }
 	else
 	  {
@@ -23103,7 +23103,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	      operand = RECUR (operand_0);
 	    else
 	      operand = uneval;
-	    RETURN (build_typeid (operand, complain));
+	    RETURN (build_typeid (operand, complain, TREE_TYPE (t)));
 	  }
       }
 
diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc
index e92e8a7ddf66..fcca2bec8841 100644
--- a/gcc/cp/rtti.cc
+++ b/gcc/cp/rtti.cc
@@ -222,31 +222,22 @@ throw_bad_typeid (void)
   return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
 }
 
-/* const type_info*.  */
-
-inline tree
-type_info_ptr_type ()
-{
-  return build_pointer_type (const_type_info_type_node);
-}
-
 /* Return a pointer to a type_info object describing TYPE, suitably
    cast to the language defined type (for typeid) or void (for building
    up the descriptors).  */
 
 static tree
-get_tinfo_ptr (tree type, bool voidp = false)
+get_tinfo_ptr (tree type, tree tinfo_ptr_type)
 {
   tree decl = get_tinfo_decl (type);
   mark_used (decl);
 
-  tree ptype = voidp ? const_ptr_type_node : type_info_ptr_type ();
-  return build_nop (ptype, build_address (decl));
+  return build_nop (tinfo_ptr_type, build_address (decl));
 }
 static inline tree
 get_void_tinfo_ptr (tree type)
 {
-  return get_tinfo_ptr (type, true);
+  return get_tinfo_ptr (type, const_ptr_type_node);
 }
 
 /* Return an lvalue expression whose type is "const std::type_info"
@@ -255,7 +246,7 @@ get_void_tinfo_ptr (tree type)
    otherwise return the static type of the expression.  */
 
 static tree
-get_tinfo_ptr_dynamic (tree exp, tsubst_flags_t complain)
+get_tinfo_ptr_dynamic (tree exp, tsubst_flags_t complain, tree tinfo_ptr_type)
 {
   tree type;
   tree t;
@@ -291,11 +282,11 @@ get_tinfo_ptr_dynamic (tree exp, tsubst_flags_t complain)
       index = build_int_cst (NULL_TREE,
 			     -1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
       t = build_vtbl_ref (exp, index);
-      t = convert (type_info_ptr_type (), t);
+      t = convert (tinfo_ptr_type, t);
     }
   else
     /* Otherwise return the type_info for the static type of the expr.  */
-    t = get_tinfo_ptr (type);
+    t = get_tinfo_ptr (type, tinfo_ptr_type);
 
   return t;
 }
@@ -371,15 +362,22 @@ typeid_evaluated_p (tree exp, int *nonnull)
    an lvalue of type "const std::type_info".  */
 
 tree
-build_typeid (tree exp, tsubst_flags_t complain)
+build_typeid (tree exp, tsubst_flags_t complain, tree tinfo_type/*=NULL_TREE*/)
 {
   tree cond = NULL_TREE, initial_expr = exp;
 
-  if (exp == error_mark_node || !typeid_ok_p ())
+  if (exp == error_mark_node)
     return error_mark_node;
 
+  if (!tinfo_type)
+    {
+      if (!typeid_ok_p ())
+	return error_mark_node;
+      tinfo_type = const_type_info_type_node;
+    }
+
   if (processing_template_decl)
-    return build_min (TYPEID_EXPR, const_type_info_type_node, exp);
+    return build_min (TYPEID_EXPR, tinfo_type, exp);
 
   int nonnull = 0;
   if (typeid_evaluated_p (exp, &nonnull))
@@ -394,7 +392,8 @@ build_typeid (tree exp, tsubst_flags_t complain)
 	}
     }
 
-  exp = get_tinfo_ptr_dynamic (exp, complain);
+  exp = get_tinfo_ptr_dynamic (exp, complain,
+			       build_pointer_type (tinfo_type));
 
   if (exp == error_mark_node)
     return error_mark_node;
@@ -528,13 +527,20 @@ get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
 /* Return the type_info object for TYPE.  */
 
 tree
-get_typeid (tree type, tsubst_flags_t complain)
+get_typeid (tree type, tsubst_flags_t complain, tree tinfo_type/*=NULL_TREE*/)
 {
-  if (type == error_mark_node || !typeid_ok_p ())
+  if (type == error_mark_node)
     return error_mark_node;
 
+  if (!tinfo_type)
+    {
+      if (!typeid_ok_p ())
+	return error_mark_node;
+      tinfo_type = const_type_info_type_node;
+    }
+
   if (processing_template_decl)
-    return build_min (TYPEID_EXPR, const_type_info_type_node, type);
+    return build_min (TYPEID_EXPR, tinfo_type, type);
 
   /* If the type of the type-id is a reference type, the result of the
      typeid expression refers to a type_info object representing the
@@ -563,7 +569,8 @@ get_typeid (tree type, tsubst_flags_t complain)
   if (!type)
     return error_mark_node;
 
-  return cp_build_fold_indirect_ref (get_tinfo_ptr (type));
+  tinfo_type = build_pointer_type (tinfo_type);
+  return cp_build_fold_indirect_ref (get_tinfo_ptr (type, tinfo_type));
 }
 
 /* Check whether TEST is null before returning RESULT.  If TEST is used in
diff --git a/gcc/testsuite/g++.dg/modules/typeid-2_a.C b/gcc/testsuite/g++.dg/modules/typeid-2_a.C
new file mode 100644
index 000000000000..d0df289f9254
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/typeid-2_a.C
@@ -0,0 +1,12 @@
+// PR c++/124888
+// { dg-additional-options -fmodules }
+
+module;
+#include <typeinfo>
+export module foo;
+
+export template <class T>
+const std::type_info &f(T *p)
+{
+  return typeid (*p);
+}
diff --git a/gcc/testsuite/g++.dg/modules/typeid-2_b.C b/gcc/testsuite/g++.dg/modules/typeid-2_b.C
new file mode 100644
index 000000000000..78a18c6c5f36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/typeid-2_b.C
@@ -0,0 +1,12 @@
+// { dg-additional-options -fmodules }
+
+import foo;
+
+struct A { };
+struct B { virtual void f() { } };
+
+void g(A* a, B* b)
+{
+  f (a);
+  f (b);
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.