c++: uninstantiated template friends
authorNathan Sidwell <nathan@acm.org>
Thu, 3 Dec 2020 19:12:08 +0000 (11:12 -0800)
committerNathan Sidwell <nathan@acm.org>
Thu, 3 Dec 2020 20:40:09 +0000 (12:40 -0800)
template friends need to be recognized by module streaming and
associated with the befriending class.  but their context is that of
the friend (a namespace or other class).  This adds a flag to mark
such templates, and uses their DECL_CHAIN to point at the befriender.

gcc/cp
* cp-tree.h (DECL_UNINSTANTIATED_TEMPLATE_FRIEND): New.
* pt.c (push_template_decl): Set it.
(tsubst_friend_function): Clear it.

gcc/cp/cp-tree.h
gcc/cp/pt.c

index 69f8ed56e629eaaff8a1b48b81b8949fe5177b23..4db5012844305d0e7372f79caadd616a45e006aa 100644 (file)
@@ -545,6 +545,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       DECL_ANON_UNION_VAR_P (in a VAR_DECL)
       DECL_SELF_REFERENCE_P (in a TYPE_DECL)
       DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL)
+      DECL_UNINSTANIATED_TEMPLATE_FRIEND_P (in TEMPLATE_DECL)
    5: DECL_INTERFACE_KNOWN.
    6: DECL_THIS_STATIC (in VAR_DECL, FUNCTION_DECL or PARM_DECL)
       DECL_FIELD_IS_BASE (in FIELD_DECL)
@@ -3161,6 +3162,13 @@ struct GTY(()) lang_decl {
   (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
    ->u.base.friend_or_tls)
 
+/* True of a TEMPLATE_DECL that is a template class friend.  Such
+   decls are not pushed until instantiated (as they may depend on
+   parameters of the befriending class).  DECL_CHAIN is the
+   befriending class.  */
+#define DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P(NODE) \
+  (DECL_LANG_FLAG_4 (TEMPLATE_DECL_CHECK (NODE)))
+
 /* Nonzero if the thread-local variable was declared with __thread as
    opposed to thread_local.  */
 #define DECL_GNU_TLS_P(NODE)                           \
index 3ca28133d942b802b51b3dae74f2847d23084e0f..08931823d576052b8788c20ecf2d57161bb7b49e 100644 (file)
@@ -22,7 +22,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Known bugs or deficiencies include:
 
      all methods must be provided in header files; can't use a source
-     file that contains only the method templates and "just win".  */
+     file that contains only the method templates and "just win".
+
+     Fixed by: C++20 modules.  */
 
 #include "config.h"
 #include "system.h"
@@ -6044,6 +6046,14 @@ push_template_decl (tree decl, bool is_friend)
              tmpl = NULL_TREE;
            }
        }
+      else if (is_friend)
+       {
+         /* Record this decl as belonging to the current class.  It's
+            not chained onto anything else.  */
+         DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = true;
+         gcc_checking_assert (!DECL_CHAIN (tmpl));
+         DECL_CHAIN (tmpl) = current_scope ();
+       }
     }
   else if (tmpl)
     /* The type may have been completed, or (erroneously) changed.  */
@@ -11053,6 +11063,7 @@ tsubst_friend_function (tree decl, tree args)
   DECL_USE_TEMPLATE (new_friend) = 0;
   if (TREE_CODE (new_friend) == TEMPLATE_DECL)
     {
+      DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (new_friend) = false;
       DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
       DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
        = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));