public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Jason Merrill <jason@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r11-10055] c++: redeclared hidden friend take 2 [PR105852] Date: Wed, 8 Jun 2022 21:31:44 +0000 (GMT) [thread overview] Message-ID: <20220608213144.44F2538CA68A@sourceware.org> (raw) 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>(); }
reply other threads:[~2022-06-08 21:31 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220608213144.44F2538CA68A@sourceware.org \ --to=jason@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
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).