[clang] [Clang][Sema] Avoid crash in overload diagnostics for invalid static deducing-this (PR #177783)
Luohao Wang via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 25 06:20:55 PST 2026
https://github.com/Luohaothu updated https://github.com/llvm/llvm-project/pull/177783
>From 3125f7131b1ed53b977077412b7e4bc227fabdaa Mon Sep 17 00:00:00 2001
From: Luohao Wang <luohaothu at live.com>
Date: Sun, 25 Jan 2026 01:17:05 +0800
Subject: [PATCH 1/2] [Clang][Sema] Avoid crash in overload diagnostics for
invalid static deducing-this (#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.
---
clang/lib/Sema/SemaOverload.cpp | 14 ++++++++------
clang/test/SemaCXX/crash-GH177741.cpp | 15 +++++++++++++++
2 files changed, 23 insertions(+), 6 deletions(-)
create mode 100644 clang/test/SemaCXX/crash-GH177741.cpp
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 at -1 {{an explicit object parameter cannot appear in a static function}}
+ // expected-note at -2 {{candidate function not viable}}
+};
+
+void foo() {
+ S s{};
+ s(0);
+ // expected-error at -1 {{no matching function for call to object of type 'S'}}
+}
>From 6bd851f0de84d858ed26f9c8c71f49bf8cecf50c Mon Sep 17 00:00:00 2001
From: Luohao Wang <luohaothu at live.com>
Date: Sun, 25 Jan 2026 22:20:23 +0800
Subject: [PATCH 2/2] Move test to cxx2b-deducing-this.cpp
---
clang/test/SemaCXX/crash-GH177741.cpp | 15 ---------------
clang/test/SemaCXX/cxx2b-deducing-this.cpp | 16 ++++++++++++++++
2 files changed, 16 insertions(+), 15 deletions(-)
delete mode 100644 clang/test/SemaCXX/crash-GH177741.cpp
diff --git a/clang/test/SemaCXX/crash-GH177741.cpp b/clang/test/SemaCXX/crash-GH177741.cpp
deleted file mode 100644
index ff40cfd57ef0f..0000000000000
--- a/clang/test/SemaCXX/crash-GH177741.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 at -1 {{an explicit object parameter cannot appear in a static function}}
- // expected-note at -2 {{candidate function not viable}}
-};
-
-void foo() {
- S s{};
- s(0);
- // expected-error at -1 {{no matching function for call to object of type 'S'}}
-}
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index a9e31c3d06676..86a60503de6c1 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -1400,3 +1400,19 @@ a void Bar(this int) { // expected-note {{candidate function}}
}
}
+
+namespace GH177741 {
+
+struct S {
+ static int operator()(this S) { return 0; }
+ // expected-error at -1 {{an explicit object parameter cannot appear in a static function}}
+ // expected-note at -2 {{candidate function not viable}}
+};
+
+void foo() {
+ S s{};
+ s(0);
+ // expected-error at -1 {{no matching function for call to object of type 'S'}}
+}
+
+}
More information about the cfe-commits
mailing list