]> granicus.if.org Git - clang/commitdiff
Explicitly track the number of call arguments provided when performing
authorDouglas Gregor <dgregor@apple.com>
Wed, 19 Jan 2011 23:54:39 +0000 (23:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 19 Jan 2011 23:54:39 +0000 (23:54 +0000)
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
lib/Sema/SemaOverload.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp

index 404d895756fb40a95ba8d6ab67952f851e6138f6..56b0f53bc61ea3308e196da7fc9cdd1f630a6f5a 100644 (file)
@@ -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 {
index a1b09d91f2d9edd97de9862580d3f3fcc1e1ea9b..0b401007b8b27796422d6445fb46206b9188327e 100644 (file)
@@ -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<CXXConversionDecl>(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.,
index 5aabebae94fc6785d496a2c322b1920e580ab925..01155e136aad610732e96a7de7a2c2a246973637 100644 (file)
@@ -31,3 +31,17 @@ void g3() {
    f3<int>( 42 );                  // expected-error{{call to 'f3' is ambiguous}}
    
 }
+
+namespace PR9006 {
+  struct X {
+    template <class Get>
+    int &f(char const* name, Get fget, char const* docstr = 0);
+  
+    template <class Get, class Set>
+    float &f(char const* name, Get fget, Set fset, char const* docstr = 0);
+  };
+
+  void test(X x) {
+    int &ir = x.f("blah", 0, "blah");
+  }
+}