diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index fa8e3600f5f4..cfc8068b96ca 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2819,6 +2819,17 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: Candidate.FinalConversion = ICS.Standard; + + // C++ [over.ics.user]p3: + // If the user-defined conversion is specified by a specialization of a + // conversion function template, the second standard conversion sequence + // shall have exact match rank. + if (Conversion->getPrimaryTemplate() && + GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_final_conversion_not_exact; + } + break; case ImplicitConversionSequence::BadConversion: @@ -4628,6 +4639,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_trivial_conversion: case ovl_fail_bad_final_conversion: + case ovl_fail_final_conversion_not_exact: return S.NoteOverloadCandidate(Fn); case ovl_fail_bad_conversion: { diff --git a/clang/lib/Sema/SemaOverload.h b/clang/lib/Sema/SemaOverload.h index d6b46e91c953..2b9604ac1462 100644 --- a/clang/lib/Sema/SemaOverload.h +++ b/clang/lib/Sema/SemaOverload.h @@ -440,7 +440,11 @@ namespace clang { /// This conversion candidate is not viable because its result /// type is not implicitly convertible to the desired type. - ovl_fail_bad_final_conversion + ovl_fail_bad_final_conversion, + + /// This conversion function template specialization candidate is not + /// viable because the final conversion was not an exact match. + ovl_fail_final_conversion_not_exact }; /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). diff --git a/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp new file mode 100644 index 000000000000..d9e0ff88bd8d --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +namespace PR6285 { + template struct identity + { typedef T type; }; + + struct D { + template + operator typename identity::type(); // expected-note{{candidate}} + }; + + int f() { return D(); } // expected-error{{no viable conversion}} +} +