]> granicus.if.org Git - clang/commitdiff
Tweak the partial ordering rules for function templates to prefer a
authorDouglas Gregor <dgregor@apple.com>
Sun, 16 Jan 2011 16:03:23 +0000 (16:03 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sun, 16 Jan 2011 16:03:23 +0000 (16:03 +0000)
non-variadic function template over a variadic one. This matches GCC
and the intent of the C++0x wording, in a way that I think is likely
to be acceptable to the committee.

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

lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp

index fddd14e28bf19024bb542d3aa287f13e8f573f55..a608bea34c8a3701c9fac8ea62534abb49391087 100644 (file)
@@ -3077,6 +3077,26 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
   return true;
 }
                                     
+/// \brief Determine whether this a function template whose parameter-type-list
+/// ends with a function parameter pack.
+static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
+  FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+  unsigned NumParams = Function->getNumParams();
+  if (NumParams == 0)
+    return false;
+  
+  ParmVarDecl *Last = Function->getParamDecl(NumParams - 1);
+  if (!Last->isParameterPack())
+    return false;
+  
+  // Make sure that no previous parameter is a parameter pack.
+  while (--NumParams > 0) {
+    if (Function->getParamDecl(NumParams - 1)->isParameterPack())
+      return false;
+  }
+  
+  return true;
+}
                                      
 /// \brief Returns the more specialized function template according
 /// to the rules of function template partial ordering (C++ [temp.func.order]).
@@ -3153,8 +3173,16 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
     return FT1;
   else if (Better2)
     return FT2;
-  else
-    return 0;
+  
+  // FIXME: This mimics what GCC implements, but doesn't match up with the
+  // proposed resolution for core issue 692. This area needs to be sorted out,
+  // but for now we attempt to maintain compatibility.
+  bool Variadic1 = isVariadicFunctionTemplate(FT1);
+  bool Variadic2 = isVariadicFunctionTemplate(FT2);
+  if (Variadic1 != Variadic2)
+    return Variadic1? FT2 : FT1;
+  
+  return 0;
 }
 
 /// \brief Determine if the two templates are equivalent.
index e17c88d178d60c640bac76ba641bfa6b5439bf6b..372317838e74d2c424335a1d75d4f25d3c464251 100644 (file)
@@ -31,16 +31,14 @@ int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1];
 
 // Partial ordering of function templates.
 template<typename T1, typename T2, typename ...Rest>
-int &f0(T1, T2, Rest...); // expected-note{{candidate function [with T1 = int, T2 = double, Rest = <>]}}
+int &f0(T1, T2, Rest...);
 
 template<typename T1, typename T2>
-float &f0(T1, T2); // expected-note{{candidate function [with T1 = int, T2 = double]}}
+float &f0(T1, T2);
 
-// FIXME: this is currently ambiguous, based on the proposed resolution
-// to core issue 692.
 void test_f0() {
   int &ir1 = f0(1, 2.0, 'a');
-  float &fr1 = f0(1, 2.0); // expected-error{{call to 'f0' is ambiguous}}
+  float &fr1 = f0(1, 2.0);
 }
 
 template<typename T1, typename T2, typename ...Rest>