diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-16 16:03:23 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-16 16:03:23 +0000 |
commit | 9da95e6eefc4b0ca25e18bdab1b703f5c185deab (patch) | |
tree | 65fc8cce902d8df09c8c95a1d1a11de89288423a | |
parent | 657ca6683d754c903026221a3aa3aa9cedb7556f (diff) |
Tweak the partial ordering rules for function templates to prefer a
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
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 32 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp | 8 |
2 files changed, 33 insertions, 7 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fddd14e28b..a608bea34c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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. diff --git a/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp b/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp index e17c88d178..372317838e 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp @@ -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> |