aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-12-03 11:12:08 -0800
committerNathan Sidwell <nathan@acm.org>2020-12-03 12:40:09 -0800
commitf7aeb823d9b0dee572015810cdb58103e91758f3 (patch)
tree57293338b9480879708331ced711d7dd83045e6c
parent3089f5feef36810c625b5813370a97b4ecc841f8 (diff)
downloadgcc-f7aeb823d9b0dee572015810cdb58103e91758f3.zip
gcc-f7aeb823d9b0dee572015810cdb58103e91758f3.tar.gz
gcc-f7aeb823d9b0dee572015810cdb58103e91758f3.tar.bz2
c++: uninstantiated template friends
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.
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/pt.c13
2 files changed, 20 insertions, 1 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 69f8ed5..4db5012 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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) \
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3ca2813..0893182 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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));