From: Douglas Gregor Date: Fri, 12 Nov 2010 23:44:13 +0000 (+0000) Subject: Implement C++ [over.match.funcs]p4 as it concerns partial ordering of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77bc572138543ef97ebec137522b763d6a6ee909;p=clang Implement C++ [over.match.funcs]p4 as it concerns partial ordering of function templates. Fixes PR8130. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118944 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index e564298fee..221b122b74 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2125,7 +2125,31 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, bool OnlyDeduced, unsigned Level, llvm::SmallVectorImpl &Deduced); - + +/// \brief If this is a non-static member function, +static void MaybeAddImplicitObjectParameterType(ASTContext &Context, + CXXMethodDecl *Method, + llvm::SmallVectorImpl &ArgTypes) { + if (Method->isStatic()) + return; + + // C++ [over.match.funcs]p4: + // + // For non-static member functions, the type of the implicit + // object parameter is + // — "lvalue reference to cv X" for functions declared without a + // ref-qualifier or with the & ref-qualifier + // - "rvalue reference to cv X" for functions declared with the + // && ref-qualifier + // + // FIXME: We don't have ref-qualifiers yet, so we don't do that part. + QualType ArgTy = Context.getTypeDeclType(Method->getParent()); + ArgTy = Context.getQualifiedType(ArgTy, + Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + ArgTy = Context.getLValueReferenceType(ArgTy); + ArgTypes.push_back(ArgTy); +} + /// \brief Determine whether the function template \p FT1 is at least as /// specialized as \p FT2. static bool isAtLeastAsSpecializedAs(Sema &S, @@ -2152,12 +2176,24 @@ static bool isAtLeastAsSpecializedAs(Sema &S, case TPOC_Call: { // - In the context of a function call, the function parameter types are // used. - unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs()); + llvm::SmallVector Args1; + if (CXXMethodDecl *Method1 = dyn_cast(FD1)) + MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1); + Args1.insert(Args1.end(), + Proto1->arg_type_begin(), Proto1->arg_type_end()); + + llvm::SmallVector Args2; + if (CXXMethodDecl *Method2 = dyn_cast(FD2)) + MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2); + Args2.insert(Args2.end(), + Proto2->arg_type_begin(), Proto2->arg_type_end()); + + unsigned NumParams = std::min(Args1.size(), Args2.size()); for (unsigned I = 0; I != NumParams; ++I) if (DeduceTemplateArgumentsDuringPartialOrdering(S, TemplateParams, - Proto2->getArgType(I), - Proto1->getArgType(I), + Args2[I], + Args1[I], Info, Deduced, QualifierComparisons)) diff --git a/test/CXX/over/over.match/over.match.funcs/p4.cpp b/test/CXX/over/over.match/over.match.funcs/p4.cpp new file mode 100644 index 0000000000..e06b86351f --- /dev/null +++ b/test/CXX/over/over.match/over.match.funcs/p4.cpp @@ -0,0 +1,16 @@ +// 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 + } +}