Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
Here friend matching tries to find a matching non-template friend and fails, so we mark the friend as a template specialization to be determined later. Then cplus_decl_attributes tries again to find a matching function and gets confused by DECL_TEMPLATE_INSTANTIATION without DECL_TEMPLATE_INFO. But it doesn't make sense for find_last_decl to be trying to match anything with DECL_USE_TEMPLATE set; those are matched elsewhere. PR c++/107484 gcc/cp/ChangeLog: * decl2.cc (find_last_decl): Return early if DECL_USE_TEMPLATE. gcc/testsuite/ChangeLog: * g++.dg/lookup/friend25.C: New test. --- gcc/cp/decl2.cc | 5 +++++ gcc/testsuite/g++.dg/lookup/friend25.C | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 gcc/testsuite/g++.dg/lookup/friend25.C diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 2b195e99997..9594be4092c 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -1613,6 +1613,11 @@ find_last_decl (tree decl) if (tree name = DECL_P (decl) ? DECL_NAME (decl) : NULL_TREE) { + /* Template specializations are matched elsewhere. */ + if (DECL_LANG_SPECIFIC (decl) + && DECL_USE_TEMPLATE (decl)) + return NULL_TREE; + /* Look up the declaration in its scope. */ tree pushed_scope = NULL_TREE; if (tree ctype = DECL_CONTEXT (decl)) diff --git a/gcc/testsuite/g++.dg/lookup/friend25.C b/gcc/testsuite/g++.dg/lookup/friend25.C new file mode 100644 index 00000000000..74cf5dc3431 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/friend25.C @@ -0,0 +1,9 @@ +// PR c++/107484 + +namespace qualified_friend_no_match { + void f(int); + template<typename T> void f(T*); + struct X { + friend void qualified_friend_no_match::f(double); // { dg-error "does not match any template" } + }; +} base-commit: 59b4a555c3f1c3dba376da1c4886a9ea18ad208d -- 2.31.1