diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 221b122b74..39996e315d 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2172,21 +2172,46 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // The types used to determine the ordering depend on the context in which // the partial ordering is done: TemplateDeductionInfo Info(S.Context, Loc); + CXXMethodDecl *Method1 = 0; + CXXMethodDecl *Method2 = 0; + bool IsNonStatic2 = false; + bool IsNonStatic1 = false; + unsigned Skip2 = 0; switch (TPOC) { case TPOC_Call: { // - In the context of a function call, the function parameter types are // used. + Method1 = dyn_cast(FD1); + Method2 = dyn_cast(FD2); + IsNonStatic1 = Method1 && !Method1->isStatic(); + IsNonStatic2 = Method2 && !Method2->isStatic(); + + // C++0x [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 + // new parameter is of type "reference to cv A," where cv are + // the cv-qualifiers of the function template (if any) and A is + // the class of which the function template is a member. + // + // 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. llvm::SmallVector Args1; - if (CXXMethodDecl *Method1 = dyn_cast(FD1)) + unsigned Skip1 = !S.getLangOptions().CPlusPlus0x && + IsNonStatic2 && !IsNonStatic1; + if (S.getLangOptions().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2) MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1); Args1.insert(Args1.end(), - Proto1->arg_type_begin(), Proto1->arg_type_end()); + Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end()); llvm::SmallVector Args2; - if (CXXMethodDecl *Method2 = dyn_cast(FD2)) + Skip2 = !S.getLangOptions().CPlusPlus0x && + IsNonStatic1 && !IsNonStatic2; + if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2); Args2.insert(Args2.end(), - Proto2->arg_type_begin(), Proto2->arg_type_end()); + Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); unsigned NumParams = std::min(Args1.size(), Args2.size()); for (unsigned I = 0; I != NumParams; ++I) @@ -2252,7 +2277,10 @@ static bool isAtLeastAsSpecializedAs(Sema &S, switch (TPOC) { case TPOC_Call: { unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs()); - for (unsigned I = 0; I != NumParams; ++I) + if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false, + TemplateParams->getDepth(), UsedParameters); + for (unsigned I = Skip2; I < NumParams; ++I) ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, TemplateParams->getDepth(), UsedParameters); diff --git a/test/CXX/over/over.match/over.match.funcs/p4.cpp b/test/CXX/over/over.match/over.match.funcs/p4.cpp deleted file mode 100644 index e06b86351f..0000000000 --- a/test/CXX/over/over.match/over.match.funcs/p4.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -namespace PR8130 { - struct A { }; - - template struct B { - template int &operator*(R&); // #1 - }; - - template float &operator*(T&, R&); // #2 - void test() { - A a; - B b; - int &ir = b * a; // calls #1a - } -} diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp new file mode 100644 index 0000000000..11ec28918e --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +// Core DR 532. +namespace PR8130 { + struct A { }; + + template struct B { + template int &operator*(R&); + }; + + template float &operator*(T&, R&); + void test() { + A a; + B b; + int &ir = b * a; + } +} diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp new file mode 100644 index 0000000000..2ffdd9579e --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace DeduceVsMember { + template + struct X { + template + int &operator==(const U& other) const; + }; + + template + float &operator==(const T&, const X&); + + void test(X xi, X xf) { + float& ir = (xi == xf); + } +}