From dfc331e04d4c6a09fb693a15fc5a57d29a198c86 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 19 Jan 2011 23:54:39 +0000 Subject: [PATCH] Explicitly track the number of call arguments provided when performing overload resolution, so that we only use that number of call arguments for partial ordering. Fixes PR9006, a recent regression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123861 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Overload.h | 4 ++++ lib/Sema/SemaOverload.cpp | 17 +++++++++++++---- .../temp.deduct/temp.deduct.partial/p11.cpp | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 404d895756..56b0f53bc6 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -549,6 +549,10 @@ namespace clang { /// Actually an OverloadFailureKind. unsigned char FailureKind; + /// \brief The number of call arguments that were explicitly provided, + /// to be used while performing partial ordering of function templates. + unsigned ExplicitCallArguments; + /// A structure used to record information about a failed /// template argument deduction. struct DeductionFailureInfo { diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a1b09d91f2..0b401007b8 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3551,7 +3551,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.Viable = true; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - + Candidate.ExplicitCallArguments = NumArgs; + unsigned NumArgsInProto = Proto->getNumArgs(); // (C++ 13.3.2p2): A candidate function having fewer than m @@ -3701,6 +3702,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.Function = Method; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; unsigned NumArgsInProto = Proto->getNumArgs(); @@ -3809,6 +3811,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; @@ -3859,6 +3862,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; @@ -3904,6 +3908,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.FinalConversion.setAllToTypes(ToType); Candidate.Viable = true; Candidate.Conversions.resize(1); + Candidate.ExplicitCallArguments = 1; // C++ [over.match.funcs]p4: // For conversion functions, the function is considered to be a member of @@ -4032,6 +4037,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = 1; Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; @@ -4071,6 +4077,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.IsSurrogate = true; Candidate.IgnoreObjectArgument = false; Candidate.Conversions.resize(NumArgs + 1); + Candidate.ExplicitCallArguments = NumArgs; // Determine the implicit conversion sequence for the implicit // object parameter. @@ -4222,6 +4229,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, // arguments. Candidate.Viable = true; Candidate.Conversions.resize(NumArgs); + Candidate.ExplicitCallArguments = NumArgs; for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { // C++ [over.match.oper]p4: // For the built-in assignment operators, conversions of the @@ -5891,16 +5899,17 @@ isBetterOverloadCandidate(Sema &S, // according to the partial ordering rules described in 14.5.5.2, or, // if not that, if (Cand1.Function && Cand1.Function->getPrimaryTemplate() && - Cand2.Function && Cand2.Function->getPrimaryTemplate()) + Cand2.Function && Cand2.Function->getPrimaryTemplate()) { if (FunctionTemplateDecl *BetterTemplate = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), Cand2.Function->getPrimaryTemplate(), Loc, isa(Cand1.Function)? TPOC_Conversion : TPOC_Call, - NumArgs)) + Cand1.ExplicitCallArguments)) return BetterTemplate == Cand1.Function->getPrimaryTemplate(); - + } + // -- the context is an initialization by user-defined conversion // (see 8.5, 13.3.1.5) and the standard conversion sequence // from the return type of F1 to the destination type (i.e., diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp index 5aabebae94..01155e136a 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -31,3 +31,17 @@ void g3() { f3( 42 ); // expected-error{{call to 'f3' is ambiguous}} } + +namespace PR9006 { + struct X { + template + int &f(char const* name, Get fget, char const* docstr = 0); + + template + float &f(char const* name, Get fget, Set fset, char const* docstr = 0); + }; + + void test(X x) { + int &ir = x.f("blah", 0, "blah"); + } +} -- 2.40.0