]> granicus.if.org Git - clang/commitdiff
Fix function template partial ordering rules for static vs. non-static
authorEli Friedman <eli.friedman@gmail.com>
Wed, 19 Sep 2012 23:27:04 +0000 (23:27 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 19 Sep 2012 23:27:04 +0000 (23:27 +0000)
functions.

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

lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp
test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp

index 0fdcd1416f94da8e0c74465a82c6158e0faa7aaf..8a30ba2884fcad95be98dab0ceb0f1059aa56dca 100644 (file)
@@ -3711,7 +3711,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
     IsNonStatic1 = Method1 && !Method1->isStatic();
     IsNonStatic2 = Method2 && !Method2->isStatic();
 
-    // C++0x [temp.func.order]p3:
+    // C++11 [temp.func.order]p3:
     //   [...] If only one of the function templates is a non-static
     //   member, that function template is considered to have a new
     //   first parameter inserted in its function parameter list. The
@@ -3719,21 +3719,24 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
     //   the cv-qualifiers of the function template (if any) and A is
     //   the class of which the function template is a member.
     //
+    // Note that we interpret this to mean "if one of the function
+    // templates is a non-static member and the other is a non-member";
+    // otherwise, the ordering rules for static functions against non-static
+    // functions don't make any sense.
+    //
     // C++98/03 doesn't have this provision, so instead we drop the
-    // first argument of the free function or static member, which
-    // seems to match existing practice.
+    // first argument of the free function, which seems to match
+    // existing practice.
     SmallVector<QualType, 4> Args1;
-    unsigned Skip1 = !S.getLangOpts().CPlusPlus0x &&
-      IsNonStatic2 && !IsNonStatic1;
-    if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2)
+    unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1;
+    if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2)
       MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1);
     Args1.insert(Args1.end(),
                  Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
 
     SmallVector<QualType, 4> Args2;
-    Skip2 = !S.getLangOpts().CPlusPlus0x &&
-      IsNonStatic1 && !IsNonStatic2;
-    if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+    Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2;
+    if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1)
       MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2);
     Args2.insert(Args2.end(),
                  Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
index 63909fb7cdbd4d2677e4bab7c91ef2ec8f4347c6..9dd683261ed0ce01d01abe5ac6b36f14e5362784 100644 (file)
@@ -15,3 +15,15 @@ namespace PR8130 {
     int &ir = b * a;
   }
 }
+
+namespace OrderWithStaticMember {
+  struct A {
+    template<class T> int g(T**, int=0) { return 0; }
+    template<class T> static int g(T*) { return 1; }
+  };
+  void f() {
+    A a;
+    int **p;
+    a.g(p);
+  }
+}
index 2ffdd9579ecd55255ca098905e155b91e49e6eae..815f8bfb5670b632ded8860597a288bdcb0d35ad 100644 (file)
@@ -14,3 +14,15 @@ namespace DeduceVsMember {
     float& ir = (xi == xf);
   }
 }
+
+namespace OrderWithStaticMember {
+  struct A {
+    template<class T> int g(T**, int=0) { return 0; }
+    template<class T> static int g(T*) { return 1; }
+  };
+  void f() {
+    A a;
+    int **p;
+    a.g(p);
+  }
+}