diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6788,9 +6788,6 @@ "%0 is %select{|in}2complete and " "%1 is %select{|in}3complete">, InGroup; -def warn_typecheck_ordered_comparison_of_function_pointers : Warning< - "ordered comparison of function pointers (%0 and %1)">, - InGroup; def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< "ordered comparison of function pointers (%0 and %1)">, InGroup; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11804,17 +11804,15 @@ if (IsOrdered && LHSType->isFunctionPointerType() && RHSType->isFunctionPointerType()) { - // Valid unless a relational comparison of function pointers - bool IsError = Opc == BO_Cmp; - auto DiagID = - IsError ? diag::err_typecheck_ordered_comparison_of_function_pointers - : getLangOpts().CPlusPlus - ? diag::warn_typecheck_ordered_comparison_of_function_pointers - : diag::ext_typecheck_ordered_comparison_of_function_pointers; - Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); + // Valid unless a relational comparison of function pointers. + bool IsError = getLangOpts().CPlusPlus; + Diag(Loc, IsError + ? diag::err_typecheck_ordered_comparison_of_function_pointers + : diag::ext_typecheck_ordered_comparison_of_function_pointers) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); if (IsError) - return QualType(); + return Opc != BO_Cmp ? Context.getLogicalOperationType() : QualType(); } if ((LHSType->isIntegerType() && !LHSIsNull) || diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -8466,7 +8466,7 @@ // bool operator==(T, T); // bool operator!=(T, T); // R operator<=>(T, T) - void addGenericBinaryPointerOrEnumeralOverloads(bool IsSpaceship) { + void addGenericBinaryPointerOrEnumeralOverloads(bool IsOrdered) { // C++ [over.match.oper]p3: // [...]the built-in candidates include all of the candidate operator // functions defined in 13.6 that, compared to the given operator, [...] @@ -8525,7 +8525,7 @@ // Don't add the same builtin candidate twice. if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second) continue; - if (IsSpaceship && PtrTy->isFunctionPointerType()) + if (IsOrdered && PtrTy->isFunctionPointerType()) continue; QualType ParamTypes[2] = {PtrTy, PtrTy}; @@ -9223,7 +9223,7 @@ case OO_EqualEqual: case OO_ExclaimEqual: OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads(); - OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false); + OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsOrdered=*/false); OpBuilder.addGenericBinaryArithmeticOverloads(); break; @@ -9231,12 +9231,12 @@ case OO_Greater: case OO_LessEqual: case OO_GreaterEqual: - OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false); + OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsOrdered=*/true); OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Spaceship: - OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/true); + OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsOrdered=*/true); OpBuilder.addThreeWayArithmeticOverloads(); break; diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -28,10 +28,10 @@ template void composite_pointer_type_is_ord() { composite_pointer_type_is_base(); - typedef __typeof(val() < val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() <= val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() > val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() >= val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} + typedef __typeof(val() < val()) cmp; + typedef __typeof(val() <= val()) cmp; + typedef __typeof(val() > val()) cmp; + typedef __typeof(val() >= val()) cmp; typedef bool cmp; } @@ -79,8 +79,8 @@ no_composite_pointer_type(); #if __cplusplus > 201402 - composite_pointer_type_is_ord(); // expected-note {{requested here}} - composite_pointer_type_is_ord(); // expected-note {{requested here}} + composite_pointer_type_is_unord(); + composite_pointer_type_is_unord(); composite_pointer_type_is_unord(); composite_pointer_type_is_unord(); // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -18,9 +18,9 @@ void operator-(S, S); void f() { - bool a = (void(*)(S, S))operator+ < // expected-warning {{ordered comparison of function pointers}} + bool a = (void(*)(S, S))operator+ < // expected-error {{ordered comparison of function pointers}} (void(*)(S, S))operator+; - bool b = (void(*)(S, S))operator- < // cxx20_2b-note {{to match this '<'}} cxx98_17-warning {{ordered comparison of function pointers}} + bool b = (void(*)(S, S))operator- < // cxx20_2b-note {{to match this '<'}} cxx98_17-error {{ordered comparison of function pointers}} (void(*)(S, S))operator-; // cxx20_2b-error {{expected '>'}} bool c = (void(*)(S, S))operator+ < // expected-note {{to match this '<'}} (void(*)(S, S))operator-; // expected-error {{expected '>'}} diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -514,9 +514,7 @@ void f(), g(); constexpr void (*pf)() = &f, (*pg)() = &g; - constexpr bool u13 = pf < pg; // expected-error {{constant expression}} expected-note {{comparison has unspecified value}} - // expected-warning@-1 {{ordered comparison of function pointers}} - constexpr bool u14 = pf == pg; + constexpr bool u13 = pf == pg; // If two pointers point to non-static data members of the same object with // different access control, the result is unspecified. diff --git a/clang/test/SemaCXX/compare-function-pointer.cpp b/clang/test/SemaCXX/compare-function-pointer.cpp --- a/clang/test/SemaCXX/compare-function-pointer.cpp +++ b/clang/test/SemaCXX/compare-function-pointer.cpp @@ -3,25 +3,48 @@ using fp0_t = void (*)(); using fp1_t = int (*)(); +namespace test_builtin { + extern fp0_t a, b; extern fp1_t c; bool eq0 = a == b; bool ne0 = a != b; -bool lt0 = a < b; // expected-warning {{ordered comparison of function pointers ('fp0_t' (aka 'void (*)()') and 'fp0_t')}} -bool le0 = a <= b; // expected-warning {{ordered comparison of function pointers}} -bool gt0 = a > b; // expected-warning {{ordered comparison of function pointers}} -bool ge0 = a >= b; // expected-warning {{ordered comparison of function pointers}} -auto tw0 = a <=> b; // expected-error {{ordered comparison of function pointers}} +bool lt0 = a < b; // expected-error {{ordered comparison of function pointers ('fp0_t' (aka 'void (*)()') and 'fp0_t')}} +bool le0 = a <= b; // expected-error {{ordered comparison of function pointers}} +bool gt0 = a > b; // expected-error {{ordered comparison of function pointers}} +bool ge0 = a >= b; // expected-error {{ordered comparison of function pointers}} bool eq1 = a == c; // expected-error {{comparison of distinct pointer types}} bool ne1 = a != c; // expected-error {{comparison of distinct pointer types}} -bool lt1 = a < c; // expected-warning {{ordered comparison of function pointers ('fp0_t' (aka 'void (*)()') and 'fp1_t' (aka 'int (*)()'))}} - // expected-error@-1 {{comparison of distinct pointer types}} -bool le1 = a <= c; // expected-warning {{ordered comparison of function pointers}} - // expected-error@-1 {{comparison of distinct pointer types}} -bool gt1 = a > c; // expected-warning {{ordered comparison of function pointers}} - // expected-error@-1 {{comparison of distinct pointer types}} -bool ge1 = a >= c; // expected-warning {{ordered comparison of function pointers}} - // expected-error@-1 {{comparison of distinct pointer types}} +bool lt1 = a < c; // expected-error {{ordered comparison of function pointers ('fp0_t' (aka 'void (*)()') and 'fp1_t' (aka 'int (*)()'))}} +bool le1 = a <= c; // expected-error {{ordered comparison of function pointers}} +bool gt1 = a > c; // expected-error {{ordered comparison of function pointers}} +bool ge1 = a >= c; // expected-error {{ordered comparison of function pointers}} auto tw1 = a <=> c; // expected-error {{ordered comparison of function pointers}} + +} // namespace test_builtin + +namespace test_overload { + +template struct wrapper { operator T(); }; + +extern wrapper a, b; +extern wrapper c; + +bool eq0 = a == b; +bool ne0 = a != b; +bool lt0 = a < b; // expected-error {{invalid operands to binary expression}} +bool le0 = a <= b; // expected-error {{invalid operands to binary expression}} +bool gt0 = a > b; // expected-error {{invalid operands to binary expression}} +bool ge0 = a >= b; // expected-error {{invalid operands to binary expression}} + +bool eq1 = a == c; // expected-error {{invalid operands to binary expression}} +bool ne1 = a != c; // expected-error {{invalid operands to binary expression}} +bool lt1 = a < c; // expected-error {{invalid operands to binary expression}} +bool le1 = a <= c; // expected-error {{invalid operands to binary expression}} +bool gt1 = a > c; // expected-error {{invalid operands to binary expression}} +bool ge1 = a >= c; // expected-error {{invalid operands to binary expression}} +auto tw1 = a <=> c; // expected-error {{invalid operands to binary expression}} + +} // namespace test_overload diff --git a/clang/test/SemaTemplate/resolve-single-template-id.cpp b/clang/test/SemaTemplate/resolve-single-template-id.cpp --- a/clang/test/SemaTemplate/resolve-single-template-id.cpp +++ b/clang/test/SemaTemplate/resolve-single-template-id.cpp @@ -68,11 +68,11 @@ one < one; // expected-warning {{self-comparison always evaluates to false}} \ // expected-warning {{relational comparison result unused}} \ - // expected-warning {{ordered comparison of function pointers}} + // expected-error {{ordered comparison of function pointers}} oneT < oneT; // expected-warning {{self-comparison always evaluates to false}} \ // expected-warning {{relational comparison result unused}} \ - // expected-warning {{ordered comparison of function pointers}} + // expected-error {{ordered comparison of function pointers}} two < two; //expected-error 2 {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{invalid operands to binary expression ('void' and 'void')}} twoT < twoT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}}