public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-10055] c++: redeclared hidden friend take 2 [PR105852]
@ 2022-06-08 21:31 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-06-08 21:31 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:3e39a0a4b71dce674ee30fe71590b0152663b6d8
commit r11-10055-g3e39a0a4b71dce674ee30fe71590b0152663b6d8
Author: Jason Merrill <jason@redhat.com>
Date: Mon Jun 6 21:49:06 2022 -0400
c++: redeclared hidden friend take 2 [PR105852]
My previous patch for 105761 avoided copying DECL_TEMPLATE_INFO from a
friend to a later definition, but in this testcase we have first a
non-friend declaration and then a definition, and we need to avoid copying
in that case as well. But we do still want to set new_template_info to
avoid GC trouble.
With this change, the modules dump correctly identifies ::foo as a
non-template function in tpl-friend-2_a.C.
Along the way I noticed that the duplicate_decls handling of
DECL_UNIQUE_FRIEND_P was backwards for templates, where we don't clobber
DECL_LANG_SPECIFIC (olddecl) with DECL_LANG_SPECIFIC (newdecl) like we do
for non-templates.
PR c++/105852
PR c++/105761
gcc/cp/ChangeLog:
* decl.c (duplicate_decls): Avoid copying template info
from non-templated friend even if newdecl isn't a definition.
Correct handling of DECL_UNIQUE_FRIEND_P on templates.
* pt.c (non_templated_friend_p): New.
* cp-tree.h (non_templated_friend_p): Declare it.
gcc/testsuite/ChangeLog:
* g++.dg/modules/tpl-friend-2_a.C: Adjust expected dump.
* g++.dg/template/friend74.C: New test.
Diff:
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/decl.c | 16 ++++++---------
gcc/cp/pt.c | 29 ++++++++++++++++++++++++++-
gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C | 2 +-
gcc/testsuite/g++.dg/template/friend74.C | 8 ++++++++
5 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a2d8c1c77b3..fded2527e5e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7242,6 +7242,7 @@ extern bool push_tinst_level_loc (tree, location_t);
extern bool push_tinst_level_loc (tree, tree, location_t);
extern void pop_tinst_level (void);
extern struct tinst_level *outermost_tinst_level(void);
+extern bool non_templated_friend_p (tree);
extern void init_template_processing (void);
extern void print_template_statistics (void);
bool template_template_parameter_p (const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index df5361d1184..679ea9c8be7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2224,8 +2224,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
check_no_redeclaration_friend_default_args
(old_result, new_result);
}
- if (!DECL_UNIQUE_FRIEND_P (old_result))
- DECL_UNIQUE_FRIEND_P (new_result) = false;
+ if (!DECL_UNIQUE_FRIEND_P (new_result))
+ DECL_UNIQUE_FRIEND_P (old_result) = false;
check_default_args (newdecl);
@@ -2580,13 +2580,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
if (LANG_DECL_HAS_MIN (newdecl))
{
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
- if (new_defines_function
- && DECL_TEMPLATE_INFO (olddecl)
- && DECL_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT
- (DECL_TI_TEMPLATE (olddecl))))
- /* Don't copy template info from a non-template friend declaration
- in a class template (PR105761). */;
- else if (DECL_TEMPLATE_INFO (newdecl))
+ if (DECL_TEMPLATE_INFO (newdecl))
{
new_template_info = DECL_TEMPLATE_INFO (newdecl);
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
@@ -2594,8 +2588,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
/* Remember the presence of explicit specialization args. */
TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (olddecl))
= TINFO_USED_TEMPLATE_ID (new_template_info);
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
}
+
+ 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);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ec8bf229740..588c46504b4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11137,6 +11137,33 @@ outermost_tinst_level (void)
return level;
}
+/* True iff T is a friend function declaration that is not itself a template
+ and is not defined in a class template. */
+
+bool
+non_templated_friend_p (tree t)
+{
+ if (t && TREE_CODE (t) == FUNCTION_DECL
+ && DECL_UNIQUE_FRIEND_P (t))
+ {
+ tree ti = DECL_TEMPLATE_INFO (t);
+ if (!ti)
+ return true;
+ /* DECL_FRIEND_CONTEXT is set for a friend defined in class. */
+ if (DECL_FRIEND_CONTEXT (t))
+ return false;
+ /* Non-templated friends in a class template are still represented with a
+ TEMPLATE_DECL; check that its primary template is the befriending
+ class. Note that DECL_PRIMARY_TEMPLATE is null for
+ template <class T> friend A<T>::f(); */
+ tree tmpl = TI_TEMPLATE (ti);
+ tree primary = DECL_PRIMARY_TEMPLATE (tmpl);
+ return (primary && primary != tmpl);
+ }
+ else
+ return false;
+}
+
/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL. ARGS is the
vector of template arguments, as for tsubst.
@@ -14079,7 +14106,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
/* This special case arises when we have something like this:
template <class T> struct S {
- friend void f<int>(int, double);
+ friend void f<int>(int, double);
};
Here, the DECL_TI_TEMPLATE for the friend declaration
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C b/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C
index 3acacf8ee34..c12857fbf69 100644
--- a/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-2_a.C
@@ -16,5 +16,5 @@ template class TPL<int>; // instantiate
void foo (int, void *);
// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template TPL'\n( \[.\]=[^\n]*'\n)* \[.\]=decl declaration '::template foo'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::TPL'} module } }
-// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo<int>'\n \[.\]=binding '::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo'\n \[.\]=binding '::foo'} module } }
// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::TPL<int>'} module } }
diff --git a/gcc/testsuite/g++.dg/template/friend74.C b/gcc/testsuite/g++.dg/template/friend74.C
new file mode 100644
index 00000000000..51708334d81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend74.C
@@ -0,0 +1,8 @@
+// PR c++/105852
+// { dg-additional-options -w }
+
+template <class> struct Local { friend Local False(int *); };
+Local<int> loc;
+Local<int> False(int *);
+void New() { False; }
+Local<int> False(int *) { return Local<int>(); }
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-06-08 21:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 21:31 [gcc r11-10055] c++: redeclared hidden friend take 2 [PR105852] Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).