]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: non-templated friends [PR105852]
authorJason Merrill <jason@redhat.com>
Tue, 7 Jun 2022 19:52:30 +0000 (15:52 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 9 May 2023 03:51:18 +0000 (23:51 -0400)
The previous patch for 105852 avoids copying DECL_TEMPLATE_INFO from a
non-templated friend, but it really shouldn't have it in the first place.

PR c++/106740
PR c++/105852

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Change non-templated friend
check to an assert.
* pt.cc (tsubst_function_decl): Don't set DECL_TEMPLATE_INFO
on non-templated friends.
(tsubst_friend_function): Adjust.

gcc/testsuite/ChangeLog:

* g++.dg/template/friend78.C: New test.

gcc/cp/decl.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/template/friend78.C [new file with mode: 0644]

index ab9a009fb7e518889cb2a21a49c67714827eb73b..42f43c122b9912e1efd28a7c795af9dda522566e 100644 (file)
@@ -2666,10 +2666,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
                  = TINFO_USED_TEMPLATE_ID (new_template_info);
            }
 
-         if (non_templated_friend_p (olddecl))
-           /* Don't copy tinfo from a non-templated friend (PR105761).  */;
-         else
-           DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+         /* We don't want to copy template info from a non-templated friend
+            (PR105761), but these shouldn't have DECL_TEMPLATE_INFO now.  */
+         gcc_checking_assert (!DECL_TEMPLATE_INFO (olddecl)
+                              || !non_templated_friend_p (olddecl));
+         DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
        }
 
       if (DECL_DECLARES_FUNCTION_P (newdecl))
index b5fabe4341ecc2f1bb236dd20bf9499c7764f61d..12d91974d32907c6c08109804943bfe8763e109b 100644 (file)
@@ -11339,9 +11339,10 @@ tsubst_friend_function (tree decl, tree args)
       tree new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
       tree new_friend_result_template_info = NULL_TREE;
       bool new_friend_is_defn =
-       (DECL_INITIAL (DECL_TEMPLATE_RESULT
-                      (template_for_substitution (new_friend)))
-        != NULL_TREE);
+       (new_friend_template_info
+        && (DECL_INITIAL (DECL_TEMPLATE_RESULT
+                          (template_for_substitution (new_friend)))
+            != NULL_TREE));
       tree not_tmpl = new_friend;
 
       if (TREE_CODE (new_friend) == TEMPLATE_DECL)
@@ -14175,6 +14176,10 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
          && !LAMBDA_FUNCTION_P (t))
        return t;
 
+      /* A non-templated friend doesn't get DECL_TEMPLATE_INFO.  */
+      if (non_templated_friend_p (t))
+       goto friend_case;
+
       /* Calculate the most general template of which R is a
         specialization.  */
       gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
@@ -14220,6 +14225,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
         tsubst_friend_function, and we want only to create a
         new decl (R) with appropriate types so that we can call
         determine_specialization.  */
+    friend_case:
       gen_tmpl = NULL_TREE;
       argvec = NULL_TREE;
     }
@@ -14415,7 +14421,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
       /* If this is an instantiation of a member template, clone it.
         If it isn't, that'll be handled by
         clone_constructors_and_destructors.  */
-      if (PRIMARY_TEMPLATE_P (gen_tmpl))
+      if (gen_tmpl && PRIMARY_TEMPLATE_P (gen_tmpl))
        clone_cdtor (r, /*update_methods=*/false);
     }
   else if ((complain & tf_error) != 0
diff --git a/gcc/testsuite/g++.dg/template/friend78.C b/gcc/testsuite/g++.dg/template/friend78.C
new file mode 100644 (file)
index 0000000..6100528
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/106740
+// { dg-additional-options -Wno-non-template-friend }
+
+template <typename> struct EnumClass { friend int toString(EnumClass); };
+struct AmhsConvInfoCoFw {
+  enum AftnTypeXMsgTypeEnum {};
+  typedef EnumClass<AftnTypeXMsgTypeEnum> AftnTypeXMsgType;
+  const int getAftnTypeXMsgTypeAsStr() const;
+  struct MtcuAxgwInfo {
+    AftnTypeXMsgType mAftnTypeXMsgType;
+  };
+};
+const int AmhsConvInfoCoFw::getAftnTypeXMsgTypeAsStr() const {
+  MtcuAxgwInfo __trans_tmp_1;
+  toString(__trans_tmp_1.mAftnTypeXMsgType);
+  return 0;
+}
+int toString(AmhsConvInfoCoFw::AftnTypeXMsgType);