Skip to content

Conversation

@cor3ntin
Copy link
Contributor

@cor3ntin cor3ntin commented Jul 10, 2025

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

…ct parameter

When an overload is invalid, we try to initialize each conversion sequence
for the purpose of recovery, but we failed to initialized explicit objects,
leading to a crash

Fixes llvm#147121
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jul 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2025

@llvm/pr-subscribers-clang

Author: Corentin Jabot (cor3ntin)

Changes

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


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

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+3-3)
  • (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (+57)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ca00a80d10eca..3f1587d8113db 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -930,6 +930,7 @@ Bug Fixes to C++ Support
 - 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 7af3acacb5ba6..1b54628c5e564 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13131,7 +13131,8 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
     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 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
 
   // 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 3a3dc8855d827..6987d0c020457 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -1290,3 +1290,60 @@ void f() {
 
 
 }
+
+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}}
+}
+}

@cor3ntin cor3ntin merged commit ab0d11c into llvm:main Jul 10, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

clang++ front end crash on combination of explicit object parameter, static_assert(): isInitialized() && "querying uninitialized conversion"

3 participants