Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -8956,6 +8956,7 @@ // instantiated from the member definition associated with its class // template. UnresolvedSet<8> Matches; + FunctionDecl *NonTemplateMatch = nullptr; AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); @@ -8966,12 +8967,22 @@ QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(), /*AdjustExceptionSpec*/true); if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) { - Matches.clear(); - + if (!Method->getPrimaryTemplate()) { + // FIXME: Can this assert ever happen? Needs a test. + assert(!NonTemplateMatch && "Multiple NonTemplateMatches"); + NonTemplateMatch = Method; + continue; + } Matches.addDecl(Method, P.getAccess()); + + // FIXME: Can this ever be true? Even so, should it really be a + // break? Needs a test. if (Method->getTemplateSpecializationKind() == TSK_Undeclared) break; + continue; } + // FIXME: Would this be considered an almost match as well? + continue; } } @@ -9012,19 +9023,22 @@ Matches.addDecl(Specialization, P.getAccess()); } - // Find the most specialized function template specialization. - UnresolvedSetIterator Result = getMostSpecialized( - Matches.begin(), Matches.end(), FailedCandidates, - D.getIdentifierLoc(), - PDiag(diag::err_explicit_instantiation_not_known) << Name, - PDiag(diag::err_explicit_instantiation_ambiguous) << Name, - PDiag(diag::note_explicit_instantiation_candidate)); - - if (Result == Matches.end()) - return true; + FunctionDecl *Specialization = NonTemplateMatch; + if (!Specialization) { + // Find the most specialized function template specialization. + UnresolvedSetIterator Result = getMostSpecialized( + Matches.begin(), Matches.end(), FailedCandidates, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); + + if (Result == Matches.end()) + return true; - // Ignore access control bits, we don't need them for redeclaration checking. - FunctionDecl *Specialization = cast(*Result); + // Ignore access control bits, we don't need them for redeclaration checking. + Specialization = cast(*Result); + } // C++11 [except.spec]p4 // In an explicit instantiation an exception-specification may be specified, Index: test/CXX/temp/temp.decls/temp.mem/p5.cpp =================================================================== --- test/CXX/temp/temp.decls/temp.mem/p5.cpp +++ test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -77,3 +77,16 @@ x0.operator float *(); x0c.operator const char*(); } + +namespace PR14211 { +template struct X { + void foo(U){} + template void foo(T){} + + template void bar(T){} + void bar(U){} +}; + +template void X::foo(int); +template void X::bar(int); +}