diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c9f9ecca727a..4888ffe6f4dfc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -837,6 +837,8 @@ Bug Fixes in This Version - Fix an issue with missing symbol definitions when the first coroutine statement appears in a discarded ``if constexpr`` branch. Fixes (`#78290 `_) +- Fixed assertion failure with deleted overloaded unary operators. + Fixes (`#78314 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 697a1c0cfc404..030878899b812 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14332,12 +14332,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, return ExprError(); case OR_Deleted: + // CreateOverloadedUnaryOp fills the first element of ArgsArray with the + // object whose method was called. Later in NoteCandidates size of ArgsArray + // is passed further and it eventually ends up compared to number of + // function candidate parameters which never includes the object parameter, + // so slice ArgsArray to make sure apples are compared to apples. CandidateSet.NoteCandidates( PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) << UnaryOperator::getOpcodeStr(Opc) << Input->getSourceRange()), - *this, OCD_AllCandidates, ArgsArray, UnaryOperator::getOpcodeStr(Opc), - OpLoc); + *this, OCD_AllCandidates, ArgsArray.drop_front(), + UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); } diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp index 83a7e65b43dd0..887848c29b83c 100644 --- a/clang/test/SemaCXX/overloaded-operator.cpp +++ b/clang/test/SemaCXX/overloaded-operator.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx23 -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 %s + class X { }; X operator+(X, X); @@ -33,7 +35,9 @@ struct A { A make_A(); -bool operator==(A&, Z&); // expected-note 3{{candidate function}} +bool operator==(A&, Z&); // expected-note 3{{candidate function}} \ + // cxx23-note 2{{candidate function}} + void h(A a, const A ac, Z z) { make_A() == z; // expected-warning{{equality comparison result unused}} @@ -68,7 +72,9 @@ struct E2 { }; // C++ [over.match.oper]p3 - enum restriction. -float& operator==(E1, E2); // expected-note{{candidate function}} +float& operator==(E1, E2); // expected-note{{candidate function}} \ + // cxx23-note{{candidate function}} + void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2, Enum1 next_enum1) { float &f1 = (e1 == e2); @@ -86,7 +92,8 @@ class pr5244_foo }; bool operator==(const pr5244_foo& s1, const pr5244_foo& s2); // expected-note{{candidate function}} -bool operator==(char c, const pr5244_foo& s); // expected-note{{candidate function}} +bool operator==(char c, const pr5244_foo& s); // expected-note{{candidate function}} \ + // cxx23-note{{candidate function}} enum pr5244_bar { @@ -130,7 +137,7 @@ struct SmartPtr { }; void test_smartptr(SmartPtr ptr, const SmartPtr cptr, - const volatile SmartPtr cvptr) { + const volatile SmartPtr cvptr) { // cxx23-warning {{volatile-qualified parameter type 'const volatile SmartPtr' is deprecated}} int &ir = *ptr; long &lr = *cptr; long &lr2 = *cvptr; @@ -598,3 +605,43 @@ namespace B { } void g(B::X x) { A::f(x); } } + +namespace GH78314 { + +class a { +public: + void operator--() = delete; // expected-note {{candidate function has been explicitly deleted}} \ + // expected-note {{candidate function not viable: requires 0 arguments, but 1 was provided}} + void operator--(int) = delete; // expected-note {{candidate function has been explicitly deleted}} \ + // expected-note {{candidate function not viable: requires 1 argument, but 0 were provided}} +}; + +class c { + void operator--(this c) = delete; //precxx23-error {{explicit object parameters are incompatible with C++ standards before C++2b}} \ + // expected-note {{candidate function has been explicitly deleted}} \ + // expected-note {{candidate function not viable: requires 0 non-object arguments, but 1 was provided}} + void operator--(this c, int) = delete; //precxx23-error {{explicit object parameters are incompatible with C++ standards before C++2b}} \ + // expected-note {{candidate function has been explicitly deleted}} \ + // expected-note {{candidate function not viable: requires 1 non-object argument, but 0 were provided}} +}; + +void foo() { + a aa; + --aa; // expected-error {{overload resolution selected deleted operator '--'}} + aa--; // expected-error {{overload resolution selected deleted operator '--'}} + + c cc; + --cc; // expected-error {{overload resolution selected deleted operator '--'}} + cc--; // expected-error {{overload resolution selected deleted operator '--'}} +} + +class b { + void operator++() = delete; // expected-note {{candidate function has been explicitly deleted}} + template void operator++(int) { // expected-note {{function template not viable: requires 1 argument, but 0 were provided}} + b bb; + ++bb; // expected-error {{overload resolution selected deleted operator '++'}} + } +}; + + +}