aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/module.cc6
-rw-r--r--gcc/cp/pt.cc18
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-nttp-1_a.C8
-rw-r--r--gcc/testsuite/g++.dg/modules/tpl-nttp-1_b.C6
5 files changed, 35 insertions, 6 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 039c707..a9ce44b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7626,7 +7626,8 @@ enum { nt_opaque = false, nt_transparent = true };
extern tree alias_template_specialization_p (const_tree, bool);
extern tree dependent_alias_template_spec_p (const_tree, bool);
extern bool dependent_opaque_alias_p (const_tree);
-extern tree get_template_parm_object (tree expr, tree mangle);
+extern tree get_template_parm_object (tree expr, tree mangle,
+ bool check_init = true);
extern tree tparm_object_argument (tree);
extern bool explicit_class_specialization_p (tree);
extern bool push_tinst_level (tree);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c3218bd..0a4ceff 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9938,7 +9938,11 @@ trees_in::tree_node (bool is_use)
tree name = tree_node ();
if (!get_overrun ())
{
- res = get_template_parm_object (init, name);
+ /* We don't want to check the initializer as that may require
+ name lookup, which could recursively start lazy loading.
+ Instead we know that INIT is already valid so we can just
+ apply that directly. */
+ res = get_template_parm_object (init, name, /*check_init=*/false);
int tag = insert (res);
dump (dumper::TREE)
&& dump ("Created nttp object:%d %N", tag, name);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 32d164f..76edc7a 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7361,10 +7361,11 @@ create_template_parm_object (tree expr, tsubst_flags_t complain)
static GTY(()) hash_map<tree, tree> *tparm_obj_values;
/* Find or build an nttp object for (already-validated) EXPR with name
- NAME. */
+ NAME. When CHECK_INIT is false we don't need to process the initialiser,
+ it's already been done. */
tree
-get_template_parm_object (tree expr, tree name)
+get_template_parm_object (tree expr, tree name, bool check_init/*=true*/)
{
tree decl = get_global_binding (name);
if (decl)
@@ -7385,11 +7386,20 @@ get_template_parm_object (tree expr, tree name)
{
/* If EXPR contains any PTRMEM_CST, they will get clobbered by
lower_var_init before we're done mangling. So store the original
- value elsewhere. */
- tree copy = unshare_constructor (expr);
+ value elsewhere. We only need to unshare EXPR if it's not yet
+ been processed. */
+ tree copy = check_init ? unshare_constructor (expr) : expr;
hash_map_safe_put<hm_ggc> (tparm_obj_values, decl, copy);
}
+ if (!check_init)
+ {
+ /* The EXPR is the already processed initializer, set it on the NTTP
+ object now so that cp_finish_decl doesn't do it again later. */
+ DECL_INITIAL (decl) = expr;
+ DECL_INITIALIZED_P (decl) = 1;
+ }
+
pushdecl_top_level_and_finish (decl, expr);
return decl;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-nttp-1_a.C b/gcc/testsuite/g++.dg/modules/tpl-nttp-1_a.C
new file mode 100644
index 0000000..46f6ecd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-nttp-1_a.C
@@ -0,0 +1,8 @@
+// PR c++/116382
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+// { dg-module-cmi m:a }
+
+module m:a;
+template <typename> struct X {};
+template <X<int> nttp> struct index {};
+template struct index<{}>;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-nttp-1_b.C b/gcc/testsuite/g++.dg/modules/tpl-nttp-1_b.C
new file mode 100644
index 0000000..a3241e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-nttp-1_b.C
@@ -0,0 +1,6 @@
+// PR c++/116382
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+// { dg-module-cmi m }
+
+export module m;
+import :a;