]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Keep tracking instantiations of static class variable templates [PR122625]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sat, 15 Nov 2025 04:11:55 +0000 (15:11 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Sun, 16 Nov 2025 10:14:00 +0000 (21:14 +1100)
r16-4930-gfd5c057c2d01 ensured that we noted all class-scope variables.
But I also added a clause to 'read_var_def' to skip all class-scope
instantiations, under the mistaken belief that this would be handled in
read_class_def.

But as the testcase shows, read_class_def cannot (and should not)
register instantiations of member variable templates, as when reading
the class it just sees the template declaration.  So this patch
re-enables tracking instantiations of class-scope variable templates.

PR c++/122625

gcc/cp/ChangeLog:

* module.cc (trees_in::read_var_def): Also track class-scope
primary template specialisations.

gcc/testsuite/ChangeLog:

* g++.dg/modules/inst-7_a.C: New test.
* g++.dg/modules/inst-7_b.C: New test.

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

index 48ee7d1e790474354fbdb03ae8ed10634743fe9a..017bacdf22314863e144b59be3c96d52e69e5864 100644 (file)
@@ -13074,8 +13074,10 @@ trees_in::read_var_def (tree decl, tree maybe_template)
          if (DECL_EXPLICIT_INSTANTIATION (decl)
              && !DECL_EXTERNAL (decl))
            setup_explicit_instantiation_definition_linkage (decl);
-         /* Class static data members are handled in read_class_def.  */
-         if (!DECL_CLASS_SCOPE_P (decl)
+         /* Class non-template static members are handled in read_class_def.
+            But still handle specialisations of member templates.  */
+         if ((!DECL_CLASS_SCOPE_P (decl)
+              || primary_template_specialization_p (decl))
              && (DECL_IMPLICIT_INSTANTIATION (decl)
                  || (DECL_EXPLICIT_INSTANTIATION (decl)
                      && !DECL_EXTERNAL (decl))))
diff --git a/gcc/testsuite/g++.dg/modules/inst-7_a.C b/gcc/testsuite/g++.dg/modules/inst-7_a.C
new file mode 100644 (file)
index 0000000..7489edf
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/122625
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+struct integral_constant {
+  void f() const {}
+};
+struct span {
+  template <int> static constexpr integral_constant __v{};
+  template <int, int> static constexpr integral_constant partial{};
+};
+template <int x> constexpr integral_constant span::partial<x, 0>{};
+
+template <typename T>
+struct nested {
+  template <typename U> static const U arr[3];
+};
+template <typename T>
+struct nested<T*> {
+  template <typename U> static const U arr[3];
+};
+template <typename T> template <typename U> const U nested<T>::arr[3] = {};
+template <typename T> template <typename U> const U nested<T*>::arr[3] = {};
+template <typename T> template <typename U> const U nested<T*>::arr<U*>[3] = {};
+
+export inline void format() {
+  span::__v<1>.f();
+  span::partial<5, 0>.f();
+  nested<int>::arr<integral_constant>[0].f();
+  nested<int*>::arr<integral_constant>[0].f();
+  nested<int*>::arr<integral_constant*>[0].f();
+}
diff --git a/gcc/testsuite/g++.dg/modules/inst-7_b.C b/gcc/testsuite/g++.dg/modules/inst-7_b.C
new file mode 100644 (file)
index 0000000..3a49b51
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/122625
+// { dg-additional-options "-fmodules" }
+
+import M;
+int main() {
+  format();
+}
+
+// { dg-final { scan-assembler {_ZNW1M4span3__vILi1EEE:} } }
+// { dg-final { scan-assembler {_ZNW1M4span7partialILi5ELi0EEE:} } }
+// { dg-final { scan-assembler {_ZNW1M6nestedIiE3arrIS_17integral_constantEE:} } }
+// { dg-final { scan-assembler {_ZNW1M6nestedIPiE3arrIS_17integral_constantEE:} } }
+// { dg-final { scan-assembler {_ZNW1M6nestedIPiE3arrIPS_17integral_constantEE:} } }