]> granicus.if.org Git - clang/commitdiff
Implement C++ [over.ics.user]p3, which restricts the final conversion
authorDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 23:42:09 +0000 (23:42 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 12 Apr 2010 23:42:09 +0000 (23:42 +0000)
from a conversion function template specialization to one of exact
match rank. We only know how to test this in C++0x with default
function template arguments, but it's also in the C++03 spec. Fixes
PR6285.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101089 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
lib/Sema/SemaOverload.h
test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp [new file with mode: 0644]

index fa8e3600f5f443f205483faa582c8b394ddf9dd0..cfc8068b96ca3207221f5d9381af29e58437227a 100644 (file)
@@ -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: {
index d6b46e91c9530920a55d983558cdb8daa4bbbab7..2b9604ac14627e21f8ecf9a25083bf4a87ee833c 100644 (file)
@@ -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/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp
new file mode 100644 (file)
index 0000000..d9e0ff8
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
+
+namespace PR6285 {
+  template<typename T> struct identity 
+  { typedef T type; };
+
+  struct D { 
+    template<typename T = short> 
+    operator typename identity<T>::type(); // expected-note{{candidate}}
+  }; 
+
+  int f() { return D(); } // expected-error{{no viable conversion}}
+}
+