]> granicus.if.org Git - clang/commitdiff
Try harder to ensure a strict weak ordering of overload candidates that
authorKaelyn Takata <rikka@google.com>
Wed, 7 May 2014 00:43:38 +0000 (00:43 +0000)
committerKaelyn Takata <rikka@google.com>
Wed, 7 May 2014 00:43:38 +0000 (00:43 +0000)
have arity mismatches.

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

include/clang/Sema/Overload.h
lib/Sema/SemaOverload.cpp

index d6dbd1226a8b826e2af6048b49a3ab24ad730b70..9618f8f10860518c453533f2626a129aaf5720a6 100644 (file)
@@ -679,6 +679,18 @@ namespace clang {
 
       return CanFix;
     }
+
+    unsigned getNumParams() const {
+      if (IsSurrogate) {
+        auto STy = Surrogate->getConversionType();
+        while (STy->isPointerType() || STy->isReferenceType())
+          STy = STy->getPointeeType();
+        return STy->getAs<FunctionProtoType>()->getNumParams();
+      }
+      if (Function)
+        return Function->getNumParams();
+      return ExplicitCallArguments;
+    }
   };
 
   /// OverloadCandidateSet - A set of overload candidates, used in C++
index 7f9e0ecd96fce2a37ac8253a97b9ab65fa1bfb06..51d130c685ed7de7fde58a496890caf55e40d8da 100644 (file)
@@ -9260,12 +9260,17 @@ struct CompareOverloadCandidatesForDisplay {
           L->FailureKind == ovl_fail_too_few_arguments) {
         if (R->FailureKind == ovl_fail_too_many_arguments ||
             R->FailureKind == ovl_fail_too_few_arguments) {
-          if (!L->Function || !R->Function) return !R->Function;
-          int LDist = std::abs((int)L->Function->getNumParams() - (int)NumArgs);
-          int RDist = std::abs((int)R->Function->getNumParams() - (int)NumArgs);
-          if (LDist == RDist)
-            return L->FailureKind == ovl_fail_too_many_arguments &&
-                   R->FailureKind == ovl_fail_too_few_arguments;
+          int LDist = std::abs((int)L->getNumParams() - (int)NumArgs);
+          int RDist = std::abs((int)R->getNumParams() - (int)NumArgs);
+          if (LDist == RDist) {
+            if (L->FailureKind == R->FailureKind)
+              // Sort non-surrogates before surrogates.
+              return !L->IsSurrogate && R->IsSurrogate;
+            // Sort candidates requiring fewer parameters than there were
+            // arguments given after candidates requiring more parameters
+            // than there were arguments given.
+            return L->FailureKind == ovl_fail_too_many_arguments;
+          }
           return LDist < RDist;
         }
         return false;