erik.pilkington updated this revision to Diff 156338. erik.pilkington added a comment.
Improve the diagnostics further. https://reviews.llvm.org/D49085 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaTemplate.cpp clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp Index: clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp =================================================================== --- clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -359,3 +359,31 @@ template void f2<int>(X<int> *); template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}} } + +namespace test16 { +template <class T> struct foo {}; // expected-note{{candidate ignored: not a function template}} +template <class T> class A { + friend void foo<T>(); // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test17 { +namespace ns { +template <class T> void foo() {} // expected-note{{candidate ignored: not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}} +} +using ns::foo; +template <class T> struct A { + friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test18 { +namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}} +namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}} +using ns1::foo; +using ns2::foo; + +template <class T> class A { + friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -8008,17 +8008,34 @@ // the correct context. DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); LookupResult::Filter F = Previous.makeFilter(); + enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing }; + SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates; while (F.hasNext()) { NamedDecl *D = F.next()->getUnderlyingDecl(); - if (!isa<FunctionTemplateDecl>(D) || - !FDLookupContext->InEnclosingNamespaceSetOf( - D->getDeclContext()->getRedeclContext())) + if (!isa<FunctionTemplateDecl>(D)) { F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D)); + continue; + } + + if (!FDLookupContext->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) { + F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D)); + continue; + } } F.done(); - // Should this be diagnosed here? - if (Previous.empty()) return true; + if (Previous.empty()) { + Diag(FD->getLocation(), + diag::err_dependent_function_template_spec_no_match); + for (auto &P : DiscardedCandidates) + Diag(P.second->getLocation(), + diag::note_dependent_function_template_spec_discard_reason) + << P.first; + return true; + } FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(), ExplicitTemplateArgs); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4103,6 +4103,12 @@ def err_explicit_specialization_inconsistent_storage_class : Error< "explicit specialization has extraneous, inconsistent storage class " "'%select{none|extern|static|__private_extern__|auto|register}0'">; +def err_dependent_function_template_spec_no_match : Error< + "no candidate function template was found for dependent" + " friend function template specialization">; +def note_dependent_function_template_spec_discard_reason : Note< + "candidate ignored: %select{not a function template" + "|not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error<
Index: clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp =================================================================== --- clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -359,3 +359,31 @@ template void f2<int>(X<int> *); template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}} } + +namespace test16 { +template <class T> struct foo {}; // expected-note{{candidate ignored: not a function template}} +template <class T> class A { + friend void foo<T>(); // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test17 { +namespace ns { +template <class T> void foo() {} // expected-note{{candidate ignored: not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}} +} +using ns::foo; +template <class T> struct A { + friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test18 { +namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}} +namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}} +using ns1::foo; +using ns2::foo; + +template <class T> class A { + friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -8008,17 +8008,34 @@ // the correct context. DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); LookupResult::Filter F = Previous.makeFilter(); + enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing }; + SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates; while (F.hasNext()) { NamedDecl *D = F.next()->getUnderlyingDecl(); - if (!isa<FunctionTemplateDecl>(D) || - !FDLookupContext->InEnclosingNamespaceSetOf( - D->getDeclContext()->getRedeclContext())) + if (!isa<FunctionTemplateDecl>(D)) { F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D)); + continue; + } + + if (!FDLookupContext->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) { + F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D)); + continue; + } } F.done(); - // Should this be diagnosed here? - if (Previous.empty()) return true; + if (Previous.empty()) { + Diag(FD->getLocation(), + diag::err_dependent_function_template_spec_no_match); + for (auto &P : DiscardedCandidates) + Diag(P.second->getLocation(), + diag::note_dependent_function_template_spec_discard_reason) + << P.first; + return true; + } FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(), ExplicitTemplateArgs); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4103,6 +4103,12 @@ def err_explicit_specialization_inconsistent_storage_class : Error< "explicit specialization has extraneous, inconsistent storage class " "'%select{none|extern|static|__private_extern__|auto|register}0'">; +def err_dependent_function_template_spec_no_match : Error< + "no candidate function template was found for dependent" + " friend function template specialization">; +def note_dependent_function_template_spec_discard_reason : Note< + "candidate ignored: %select{not a function template" + "|not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits