https://gcc.gnu.org/g:9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d

commit r15-7560-g9f1f4efc06f43b1ba8c1cf5a31d5b73d6a2bb12d
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Wed Feb 12 19:15:22 2025 +1100

    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 <nathanielosh...@gmail.com>
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/cp-tree.h                          |  1 +
 gcc/cp/decl2.cc                           | 22 ++++++++++++++--------
 gcc/testsuite/g++.dg/modules/pr118846_a.C | 18 ++++++++++++++++++
 gcc/testsuite/g++.dg/modules/pr118846_b.C | 10 ++++++++++
 4 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d87cc1555b7a..84bcbf29fa02 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 0217a8e24740..476e1a8abba2 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 000000000000..bbbdde78457d
--- /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 000000000000..a2f288946304
--- /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);

Reply via email to