]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: modules ICE with typename friend
authorPatrick Palka <ppalka@redhat.com>
Sat, 17 Sep 2022 13:16:53 +0000 (09:16 -0400)
committerPatrick Palka <ppalka@redhat.com>
Sat, 17 Sep 2022 13:16:53 +0000 (09:16 -0400)
A couple of xtreme-header-* modules tests began ICEing in C++23 mode
ever since r13-2650-g5d84a4418aa962 which introduced into <ranges> a
dependently scoped friend declaration:

  friend /* typename */ _OuterIter::value_type;

This happens because the streaming code assumes a TYPE_P friend must
be a class type, but here it's a TYPENAME_TYPE, which doesn't have
a TEMPLATE_INFO or CLASSTYPE_BEFRIENDING_CLASSES.  This patch tries
to correct this in a minimal way.

gcc/cp/ChangeLog:

* module.cc (friend_from_decl_list): Don't consider
CLASSTYPE_TEMPLATE_INFO for a TYPENAME_TYPE friend.
(trees_in::read_class_def): Don't add to
CLASSTYPE_BEFRIENDING_CLASSES for a TYPENAME_TYPE friend.

gcc/testsuite/ChangeLog:

* g++.dg/modules/typename-friend_a.C: New test.
* g++.dg/modules/typename-friend_b.C: New test.

gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/typename-friend_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/typename-friend_b.C [new file with mode: 0644]

index f27f4d091e5e3a95a6ba55a18e67b7003861b39d..1a1ff5be57474485fb99543fb0ccdd2c0a5c3ef1 100644 (file)
@@ -4734,7 +4734,8 @@ friend_from_decl_list (tree frnd)
       if (TYPE_P (frnd))
        {
          res = TYPE_NAME (frnd);
-         if (CLASSTYPE_TEMPLATE_INFO (frnd))
+         if (CLASS_TYPE_P (frnd)
+             && CLASSTYPE_TEMPLATE_INFO (frnd))
            tmpl = CLASSTYPE_TI_TEMPLATE (frnd);
        }
       else if (DECL_TEMPLATE_INFO (frnd))
@@ -12121,7 +12122,7 @@ trees_in::read_class_def (tree defn, tree maybe_template)
            {
              tree f = TREE_VALUE (friend_classes);
 
-             if (TYPE_P (f))
+             if (CLASS_TYPE_P (f))
                {
                  CLASSTYPE_BEFRIENDING_CLASSES (f)
                    = tree_cons (NULL_TREE, type,
diff --git a/gcc/testsuite/g++.dg/modules/typename-friend_a.C b/gcc/testsuite/g++.dg/modules/typename-friend_a.C
new file mode 100644 (file)
index 0000000..aa426fe
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+template<class T>
+struct A {
+  friend typename T::type;
+  friend void f(A) { }
+private:
+  static constexpr int value = 42;
+};
diff --git a/gcc/testsuite/g++.dg/modules/typename-friend_b.C b/gcc/testsuite/g++.dg/modules/typename-friend_b.C
new file mode 100644 (file)
index 0000000..97da9d8
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules-ts" }
+module foo;
+
+struct C;
+struct B { using type = C; };
+struct C { static_assert(A<B>::value == 42); };