hintonda updated this revision to Diff 48031. hintonda added a comment. - Added assert and additional test
http://reviews.llvm.org/D17215 Files: lib/Sema/SemaTemplate.cpp test/SemaCXX/pr14211-crash-on-invalid.cpp
Index: test/SemaCXX/pr14211-crash-on-invalid.cpp =================================================================== --- /dev/null +++ test/SemaCXX/pr14211-crash-on-invalid.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// Don't crash (PR14211). + +template<class T> +struct X { + void bar(T t) {} + void foo(T t, int i) {} + template<class U> + void foo(T t, U i) {} +}; + +template class X<double>; // expected-note {{previous explicit instantiation is here}} +template void X<double>::foo(double t, int i); // expected-error {{duplicate explicit instantiation of 'foo'}} +template void X<double>::foo<int>(double t, int i); + + + +template <class T, class U> +class A { + void foo(T) {} // expected-note {{previous declaration is here}} + void foo(U) {} // expected-error {{multiple overloads of 'foo' instantiate to the same signature 'void (int)'}} +}; +template void A<int, int>::foo(int); // expected-note {{in instantiation of template class 'A<int, int>' requested here}} Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -7825,20 +7825,26 @@ // A member function [...] of a class template can be explicitly // instantiated from the member definition associated with its class // template. - UnresolvedSet<8> Matches; + UnresolvedSet<8> TemplateMatches; + FunctionDecl *NonTemplateMatch = nullptr; TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; if (!HasExplicitTemplateArgs) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) { QualType Adjusted = adjustCCAndNoReturn(R, Method->getType()); if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) { - Matches.clear(); + if (Method->getPrimaryTemplate()){ + TemplateMatches.clear(); - Matches.addDecl(Method, P.getAccess()); - if (Method->getTemplateSpecializationKind() == TSK_Undeclared) - break; + TemplateMatches.addDecl(Method, P.getAccess()); + if (Method->getTemplateSpecializationKind() == TSK_Undeclared) + break; + } else { + assert(!NonTemplateMatch && "Found more than one non-template match"); + NonTemplateMatch = Method; + } } } } @@ -7862,22 +7868,25 @@ continue; } - Matches.addDecl(Specialization, P.getAccess()); + TemplateMatches.addDecl(Specialization, P.getAccess()); } + FunctionDecl *Specialization = NonTemplateMatch; // 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; + if (!Specialization) { + UnresolvedSetIterator Result = getMostSpecialized( + TemplateMatches.begin(), TemplateMatches.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 == TemplateMatches.end()) + return true; - // Ignore access control bits, we don't need them for redeclaration checking. - FunctionDecl *Specialization = cast<FunctionDecl>(*Result); + // Ignore access control bits, we don't need them for redeclaration checking. + Specialization = cast<FunctionDecl>(*Result); + } // C++11 [except.spec]p4 // In an explicit instantiation an exception-specification may be specified,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits