aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2025-02-12 19:15:22 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2025-02-15 23:30:09 +1100
commit9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d (patch)
tree970245a15f6640dbee6efd2797caf21067409bb8 /gcc
parent741073460b9a850ca85b01509e08bf72900b6c8a (diff)
downloadgcc-9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d.zip
gcc-9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d.tar.gz
gcc-9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d.tar.bz2
c++/modules: Don't treat template parameters as TU-local [PR118846]
There are two separate issues making various template parameters behave as if they were TU-local. Firstly, the TU-local detection code uses WILDCARD_TYPE_P to check for types that are not yet concrete; for some reason UNBOUND_CLASS_TEMPLATE is not on that list. I don't see any particular reason why it shouldn't be, so this patch adds it; this may solve other latent issues as well. Secondly, the TEMPLATE_DECL for a type with expressions involving TEMPLATE_TEMPLATE_PARM_Ps is currently always constrained to internal linkage, because the result does not have TREE_PUBLIC set. Rather than messing with TREE_PUBLIC here, I think rather we just should ensure that we only attempt to constrain visiblity of templates of type, variable, or function decls. PR c++/118846 gcc/cp/ChangeLog: * cp-tree.h (WILDCARD_TYPE_P): Include UNBOUND_CLASS_TEMPLATE. * decl2.cc (min_vis_expr_r): Don't assume a TEMPLATE_DECL will be a function or variable. gcc/testsuite/ChangeLog: * g++.dg/modules/pr118846_a.C: New test. * g++.dg/modules/pr118846_b.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.cc22
-rw-r--r--gcc/testsuite/g++.dg/modules/pr118846_a.C18
-rw-r--r--gcc/testsuite/g++.dg/modules/pr118846_b.C10
4 files changed, 43 insertions, 8 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d87cc15..84bcbf2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2325,6 +2325,7 @@ enum languages { lang_c, lang_cplusplus };
|| TREE_CODE (T) == TYPENAME_TYPE \
|| TREE_CODE (T) == TYPEOF_TYPE \
|| TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \
+ || TREE_CODE (T) == UNBOUND_CLASS_TEMPLATE \
|| TREE_CODE (T) == DECLTYPE_TYPE \
|| TREE_CODE (T) == TRAIT_TYPE \
|| TREE_CODE (T) == DEPENDENT_OPERATOR_TYPE \
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 0217a8e..476e1a8 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2813,6 +2813,19 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data)
tree t = *tp;
if (TREE_CODE (t) == PTRMEM_CST)
t = PTRMEM_CST_MEMBER (t);
+
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ if (DECL_ALIAS_TEMPLATE_P (t) || concept_definition_p (t))
+ /* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for
+ alias templates so we can't trust it here (PR107906). Ditto
+ for concepts. */
+ return NULL_TREE;
+ t = DECL_TEMPLATE_RESULT (t);
+ if (!t)
+ return NULL_TREE;
+ }
+
switch (TREE_CODE (t))
{
case CAST_EXPR:
@@ -2824,17 +2837,10 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data)
case NEW_EXPR:
case CONSTRUCTOR:
case LAMBDA_EXPR:
+ case TYPE_DECL:
tpvis = type_visibility (TREE_TYPE (t));
break;
- case TEMPLATE_DECL:
- if (DECL_ALIAS_TEMPLATE_P (t) || concept_definition_p (t))
- /* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for
- alias templates so we can't trust it here (PR107906). Ditto
- for concepts. */
- break;
- t = DECL_TEMPLATE_RESULT (t);
- /* Fall through. */
case VAR_DECL:
case FUNCTION_DECL:
if (decl_constant_var_p (t))
diff --git a/gcc/testsuite/g++.dg/modules/pr118846_a.C b/gcc/testsuite/g++.dg/modules/pr118846_a.C
new file mode 100644
index 0000000..bbbdde7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr118846_a.C
@@ -0,0 +1,18 @@
+// PR c++/118846
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+
+template <int N> struct integral_constant { static constexpr int value = N; };
+template <template <class> class> constexpr int cx_count_if() { return 0; }
+template <template <class> class P> struct mp_count_if_impl {
+ using type = integral_constant<cx_count_if<P>()>;
+};
+
+template <template <class> class> struct consume {
+ static constexpr bool value = true;
+};
+template <class P> struct use {
+ using type = consume<P::template fn>;
+};
diff --git a/gcc/testsuite/g++.dg/modules/pr118846_b.C b/gcc/testsuite/g++.dg/modules/pr118846_b.C
new file mode 100644
index 0000000..a2f2889
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr118846_b.C
@@ -0,0 +1,10 @@
+// PR c++/118846
+// { dg-additional-options "-fmodules" }
+
+module M;
+
+template <typename> struct S {
+ template <typename> struct fn {};
+};
+static_assert(mp_count_if_impl<S>::type::value == 0);
+static_assert(use<S<int>>::type::value);