]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Fix type lookup in DECL_TEMPLATE_INSTANTIATIONS [PR116364]
authorNathaniel Shead <nathanieloshead@gmail.com>
Thu, 15 Aug 2024 11:46:09 +0000 (21:46 +1000)
committerNathaniel Shead <nathanieloshead@gmail.com>
Tue, 20 Aug 2024 07:13:53 +0000 (17:13 +1000)
We need to use the DECL_TEMPLATE_INSTANTIATIONS property to find
reachable specialisations from a template to ensure that any GM
specialisations are properly marked as reachable.

Currently the modules code uses the decl when rebuilding this property,
but this is not always correct; it appears that for type specialisations
we need to use the TREE_TYPE of the decl instead so that the
specialisation is correctly found.  This patch makes the required
adjustments.

PR c++/116364

gcc/cp/ChangeLog:

* cp-tree.h (get_mergeable_specialization_flags): Adjust
signature.
* module.cc (trees_out::decl_value): Indicate whether this is a
type or decl specialisation.
* pt.cc (get_mergeable_specialization_flags): Match against the
type of a non-decl specialisation.
(add_mergeable_specialization): Use the already calculated spec
instead of always adding decl to DECL_TEMPLATE_INSTANTIATIONS.

gcc/testsuite/ChangeLog:

* g++.dg/modules/tpl-spec-9_a.C: New test.
* g++.dg/modules/tpl-spec-9_b.C: New test.
* g++.dg/modules/tpl-spec-9_c.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/cp-tree.h
gcc/cp/module.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/modules/tpl-spec-9_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/tpl-spec-9_b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/tpl-spec-9_c.C [new file with mode: 0644]

index a53fbcb43ec43d85d73c862380b8013d8250bffb..039c70710a28a82cadaadf6b1482247b948b335f 100644 (file)
@@ -7672,7 +7672,8 @@ extern void walk_specializations          (bool,
                                                          void *),
                                                 void *);
 extern tree match_mergeable_specialization     (bool is_decl, spec_entry *);
-extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
+extern unsigned get_mergeable_specialization_flags (bool is_decl, tree tmpl,
+                                                   tree spec);
 extern void add_mergeable_specialization        (bool is_decl, spec_entry *,
                                                 tree outer, unsigned);
 extern tree add_to_template_args               (tree, tree);
index f4d137b13a170551ff0c3f354cd8f9dc5a7d6be2..c3218bd5caf3a53785e2bd4ceb02f80ac6ad9fb8 100644 (file)
@@ -7981,7 +7981,8 @@ trees_out::decl_value (tree decl, depset *dep)
              auto *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
 
              if (streaming_p ())
-               u (get_mergeable_specialization_flags (entry->tmpl, decl));
+               u (get_mergeable_specialization_flags (mk & MK_tmpl_decl_mask,
+                                                      entry->tmpl, decl));
              tree_node (entry->tmpl);
              tree_node (entry->args);
            }
index 684ee0c8a60bbb5443bfa4c1e68708c84e470e8d..32d164f0fd5b75bfcad2007fd3252ed090e95344 100644 (file)
@@ -31561,13 +31561,14 @@ match_mergeable_specialization (bool decl_p, spec_entry *elt)
    specialization lists of TMPL.  */
 
 unsigned
-get_mergeable_specialization_flags (tree tmpl, tree decl)
+get_mergeable_specialization_flags (bool decl_p, tree tmpl, tree decl)
 {
   unsigned flags = 0;
 
+  tree spec = decl_p ? decl : TREE_TYPE (decl);
   for (tree inst = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
        inst; inst = TREE_CHAIN (inst))
-    if (TREE_VALUE (inst) == decl)
+    if (TREE_VALUE (inst) == spec)
       {
        flags |= 1;
        break;
@@ -31625,7 +31626,8 @@ add_mergeable_specialization (bool decl_p, spec_entry *elt, tree decl,
 
   if (flags & 1)
     DECL_TEMPLATE_INSTANTIATIONS (elt->tmpl)
-      = tree_cons (elt->args, decl, DECL_TEMPLATE_INSTANTIATIONS (elt->tmpl));
+      = tree_cons (elt->args, elt->spec,
+                  DECL_TEMPLATE_INSTANTIATIONS (elt->tmpl));
 
   if (flags & 2)
     {
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-9_a.C b/gcc/testsuite/g++.dg/modules/tpl-spec-9_a.C
new file mode 100644 (file)
index 0000000..d7c02bb
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/116364
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi foo:part }
+
+module;
+template <typename> struct S {};
+template <> struct S<int>
+  { static constexpr bool value = true; };
+export module foo:part;
+
+export template <typename T>
+  constexpr bool result = S<T>::value;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-9_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-9_b.C
new file mode 100644 (file)
index 0000000..f2ce5c2
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/116364
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+export import :part;
diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-9_c.C b/gcc/testsuite/g++.dg/modules/tpl-spec-9_c.C
new file mode 100644 (file)
index 0000000..e792245
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/116364
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+bool x = result<int>;