Fix argument numbering confusion when diagnosing a non-viable operator().
authorRichard Smith <richard@metafoo.co.uk>
Tue, 29 Oct 2019 20:06:34 +0000 (13:06 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Tue, 29 Oct 2019 20:08:39 +0000 (13:08 -0700)
This could lead to crashes if operator() is a variadic template, as we
could end up asking for an out-of-bounds argument.

clang/lib/Sema/SemaOverload.cpp
clang/test/SemaCXX/overload-member-call.cpp

index 1547108..2987007 100644 (file)
@@ -11001,7 +11001,8 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
         !isa<CXXConstructorDecl>(Cand->Function)) {
       // Conversion 0 is 'this', which doesn't have a corresponding parameter.
       ConvIdx = 1;
-      if (CSK == OverloadCandidateSet::CSK_Operator)
+      if (CSK == OverloadCandidateSet::CSK_Operator &&
+          Cand->Function->getDeclName().getCXXOverloadedOperator() != OO_Call)
         // Argument 0 is 'this', which doesn't have a corresponding parameter.
         ArgIdx = 1;
     }
@@ -11016,9 +11017,10 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
   for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0;
        ConvIdx != ConvCount;
        ++ConvIdx, ++ArgIdx, ParamIdx += (Reversed ? -1 : 1)) {
+    assert(ArgIdx < Args.size() && "no argument for this arg conversion");
     if (Cand->Conversions[ConvIdx].isInitialized()) {
       // We've already checked this conversion.
-    } else if (ArgIdx < ParamTypes.size()) {
+    } else if (ParamIdx < ParamTypes.size()) {
       if (ParamTypes[ParamIdx]->isDependentType())
         Cand->Conversions[ConvIdx].setAsIdentityConversion(
             Args[ArgIdx]->getType());
index 41f3946..90f95fc 100644 (file)
@@ -114,3 +114,10 @@ namespace b7398190 {
   const S *p;
   int k = p->f(); // expected-error {{no matching member function for call to 'f'}}
 }
+
+void member_call_op_template(int *p) {
+  // Ensure that we don't get confused about relative parameter / argument
+  // indexing here.
+  [](int, int, auto...){}(p, p); // expected-error {{no matching function}} expected-note {{no known conversion}}
+}
+