[Clang] Fix a crash when diagnosing wrong conversion to explicit object parameter (#147996)
When an overload is invalid, we try to initialize each conversion
sequence for the purpose of diagmostics, but we failed to initialize
explicit objects, leading to a crash
Fixes #147121
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b6af43c..9e16613 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -932,6 +932,7 @@
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
- Correctly handles calling an explicit object member function template overload set
through its address (``(&Foo::bar<baz>)()``).
+- Fix a crash when forming an invalid call to an operator with an explicit object member. (#GH147121)
- Correctly handle allocations in the condition of a ``if constexpr``.(#GH120197) (#GH134820)
- Fixed a crash when handling invalid member using-declaration in C++20+ mode. (#GH63254)
- Fixed parsing of lambda expressions that appear after ``*`` or ``&`` in contexts where a declaration can appear. (#GH63880)
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 7af3aca..1b54628 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13131,7 +13131,8 @@
ParamTypes =
Cand->Function->getType()->castAs<FunctionProtoType>()->getParamTypes();
if (isa<CXXMethodDecl>(Cand->Function) &&
- !isa<CXXConstructorDecl>(Cand->Function) && !Reversed) {
+ !isa<CXXConstructorDecl>(Cand->Function) && !Reversed &&
+ !Cand->Function->hasCXXExplicitFunctionObjectParameter()) {
// Conversion 0 is 'this', which doesn't have a corresponding parameter.
ConvIdx = 1;
if (CSK == OverloadCandidateSet::CSK_Operator &&
@@ -13149,9 +13150,8 @@
// Fill in the rest of the conversions.
for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0;
- ConvIdx != ConvCount;
+ ConvIdx != ConvCount && ArgIdx < Args.size();
++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 (ParamIdx < ParamTypes.size()) {
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index 3a3dc885..6987d0c 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -1290,3 +1290,60 @@
}
+
+namespace GH147121 {
+struct X {};
+struct S1 {
+ bool operator==(this auto &&, const X &); // #S1-cand
+};
+struct S2 {
+ bool operator==(this X, const auto &&); // #S2-cand
+};
+
+struct S3 {
+ S3& operator++(this X); // #S3-inc-cand
+ S3& operator++(this int); // #S3-inc-cand
+ int operator[](this X); // #S3-sub-cand
+ int operator[](this int); // #S3-sub-cand2
+ void f(this X); // #S3-f-cand
+ void f(this int); // #S3-f-cand2
+};
+
+int main() {
+ S1{} == S1{};
+ // expected-error@-1 {{invalid operands to binary expression ('S1' and 'S1')}}
+ // expected-note@#S1-cand {{candidate function template not viable}}
+ // expected-note@#S1-cand {{candidate function (with reversed parameter order) template not viable}}
+
+
+ S1{} != S1{};
+ // expected-error@-1 {{invalid operands to binary expression ('S1' and 'S1')}}
+ // expected-note@#S1-cand {{candidate function template not viable}}
+ // expected-note@#S1-cand {{candidate function (with reversed parameter order) template not viable}}
+
+
+ S2{} == S2{};
+ // expected-error@-1 {{invalid operands to binary expression ('S2' and 'S2')}}
+ // expected-note@#S2-cand {{candidate function template not viable}}
+ // expected-note@#S2-cand {{candidate function (with reversed parameter order) template not viable}}
+
+
+ S2{} != S2{};
+ // expected-error@-1 {{invalid operands to binary expression ('S2' and 'S2')}}
+ // expected-note@#S2-cand {{candidate function template not viable}}
+ // expected-note@#S2-cand {{candidate function (with reversed parameter order) template not viable}}
+
+ S3 s3;
+ ++s3;
+ // expected-error@-1{{cannot increment value of type 'S3'}}
+ s3[];
+ // expected-error@-1{{no viable overloaded operator[] for type 'S3'}}
+ // expected-note@#S3-sub-cand {{candidate function not viable: no known conversion from 'S3' to 'X' for object argument}}
+ // expected-note@#S3-sub-cand2 {{candidate function not viable: no known conversion from 'S3' to 'int' for object argument}}
+
+ s3.f();
+ // expected-error@-1{{no matching member function for call to 'f'}}
+ // expected-note@#S3-f-cand {{candidate function not viable: no known conversion from 'S3' to 'X' for object argument}}
+ // expected-note@#S3-f-cand2 {{candidate function not viable: no known conversion from 'S3' to 'int' for object argument}}
+}
+}