llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Luohao Wang (Luohaothu)

<details>
<summary>Changes</summary>

 Fix #<!-- -->177741

Overload candidate diagnostics reserve a conversion slot for the object 
argument. For static methods this slot does not correspond to a real parameter, 
and for ill-formed declarations with an explicit object parameter we could 
index past the parameter list and crash in assert builds.

Use isExplicitObjectMemberFunction() when mapping conversion slots to 
parameters and guard parameter-range computation to keep notes robust.

---
Full diff: https://github.com/llvm/llvm-project/pull/177783.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaOverload.cpp (+8-6) 
- (added) clang/test/SemaCXX/crash-GH177741.cpp (+15) 


``````````diff
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a4f6b23066736..41b0b64409fd5 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11874,7 +11874,7 @@ static void DiagnoseBadConversion(Sema &S, 
OverloadCandidate *Cand,
       !isa<CXXConstructorDecl>(Fn)) {
     if (I == 0)
       isObjectArgument = true;
-    else if (!Fn->hasCXXExplicitFunctionObjectParameter())
+    else if (!cast<CXXMethodDecl>(Fn)->isExplicitObjectMemberFunction())
       I--;
   }
 
@@ -11894,7 +11894,7 @@ static void DiagnoseBadConversion(Sema &S, 
OverloadCandidate *Cand,
       llvm::any_of(Fn->parameters().take_front(I), [](const ParmVarDecl *Parm) 
{
         return Parm->isParameterPack();
       });
-  if (!isObjectArgument && !HasParamPack)
+  if (!isObjectArgument && !HasParamPack && I < Fn->getNumParams())
     ToParamRange = Fn->getParamDecl(I)->getSourceRange();
 
   if (FromTy == S.Context.OverloadTy) {
@@ -12185,13 +12185,15 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl 
*Found, Decl *D,
   std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
       ClassifyOverloadCandidate(S, Found, Fn, CRK_None, Description);
 
+  unsigned FirstNonObjectParamIdx = HasExplicitObjectParam ? 1 : 0;
   if (modeCount == 1 && !IsAddressOf &&
-      Fn->getParamDecl(HasExplicitObjectParam ? 1 : 0)->getDeclName())
+      FirstNonObjectParamIdx < Fn->getNumParams() &&
+      Fn->getParamDecl(FirstNonObjectParamIdx)->getDeclName())
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
         << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
-        << Description << mode
-        << Fn->getParamDecl(HasExplicitObjectParam ? 1 : 0) << NumFormalArgs
-        << HasExplicitObjectParam << Fn->getParametersSourceRange();
+        << Description << mode << Fn->getParamDecl(FirstNonObjectParamIdx)
+        << NumFormalArgs << HasExplicitObjectParam
+        << Fn->getParametersSourceRange();
   else
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
         << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
diff --git a/clang/test/SemaCXX/crash-GH177741.cpp 
b/clang/test/SemaCXX/crash-GH177741.cpp
new file mode 100644
index 0000000000000..ff40cfd57ef0f
--- /dev/null
+++ b/clang/test/SemaCXX/crash-GH177741.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2b %s
+
+// https://github.com/llvm/llvm-project/issues/177741
+
+struct S {
+  static int operator()(this S) { return 0; }
+  // expected-error@-1 {{an explicit object parameter cannot appear in a 
static function}}
+  // expected-note@-2 {{candidate function not viable}}
+};
+
+void foo() {
+  S s{};
+  s(0);
+  // expected-error@-1 {{no matching function for call to object of type 'S'}}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/177783
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to