Author: Matheus Izvekov
Date: 2021-06-26T00:08:02+02:00
New Revision: ad14b5b008e2f643cb989ec645f12bf26a8659bb

URL: 
https://github.com/llvm/llvm-project/commit/ad14b5b008e2f643cb989ec645f12bf26a8659bb
DIFF: 
https://github.com/llvm/llvm-project/commit/ad14b5b008e2f643cb989ec645f12bf26a8659bb.diff

LOG: [clang] Stop providing builtin overload candidate for relational function 
pointer comparisons

Word on the grapevine was that the committee had some discussion that
ended with unanimous agreement on eliminating relational function pointer 
comparisons.

We wanted to be bold and just ban all of them cold turkey.
But then we chickened out at the last second and are going for
eliminating just the spaceship overload candidate instead, for now.

See D104680 for reference.

This should be fine and "safe", because the only possible semantic change this
would cause is that overload resolution could possibly be ambiguous if
there was another viable candidate equally as good.

But to save face a little we are going to:
* Issue an "error" for three-way comparisons on function pointers.
  But all this is doing really is changing one vague error message,
  from an "invalid operands to binary expression" into an
  "ordered comparison of function pointers", which sounds more like we mean 
business.
* Otherwise "warn" that comparing function pointers like that is totally
  not cool (unless we are told to keep quiet about this).

Signed-off-by: Matheus Izvekov <mizve...@gmail.com>

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D104892

Added: 
    clang/test/SemaCXX/compare-function-pointer.cpp

Modified: 
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
    clang/test/CXX/drs/dr15xx.cpp
    clang/test/CXX/drs/dr3xx.cpp
    clang/test/CXX/expr/expr.const/p2-0x.cpp
    clang/test/FixIt/fixit.cpp
    clang/test/Parser/cxx-template-argument.cpp
    clang/test/Sema/compare.c
    clang/test/SemaCXX/compare-cxx2a.cpp
    clang/test/SemaTemplate/resolve-single-template-id.cpp
    compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index ca8e05f27fc5..f35c105964a3 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -525,6 +525,7 @@ def OpenCLUnsupportedRGBA: 
DiagGroup<"opencl-unsupported-rgba">;
 def UnderalignedExceptionObject : DiagGroup<"underaligned-exception-object">;
 def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
 def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
+def OrderedCompareFunctionPointers : 
DiagGroup<"ordered-compare-function-pointers">;
 def Packed : DiagGroup<"packed">;
 def Padded : DiagGroup<"padded">;
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b114cdff1d94..b5b8bc6aa3c5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6794,9 +6794,14 @@ def ext_typecheck_compare_complete_incomplete_pointers : 
Extension<
   "%0 is %select{|in}2complete and "
   "%1 is %select{|in}3complete">,
   InGroup<C11>;
+def warn_typecheck_ordered_comparison_of_function_pointers : Warning<
+  "ordered comparison of function pointers (%0 and %1)">,
+  InGroup<OrderedCompareFunctionPointers>;
 def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
   "ordered comparison of function pointers (%0 and %1)">,
-  InGroup<DiagGroup<"ordered-compare-function-pointers">>;
+  InGroup<OrderedCompareFunctionPointers>;
+def err_typecheck_ordered_comparison_of_function_pointers : Error<
+  "ordered comparison of function pointers (%0 and %1)">;
 def ext_typecheck_comparison_of_fptr_to_void : Extension<
   "equality comparison between function pointer and void pointer (%0 and %1)">;
 def err_typecheck_comparison_of_fptr_to_void : Error<
@@ -9143,9 +9148,6 @@ def 
note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
   "%select{|member|base class}0 %1 declared here">;
 def note_defaulted_comparison_cannot_deduce_callee : Note<
   "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
-def note_defaulted_comparison_selected_invalid : Note<
-  "would compare %select{|member|base class}0 %1 "
-  "as %2, which does not support relational comparisons">;
 def err_incorrect_defaulted_comparison_constexpr : Error<
   "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
   "three-way comparison operator}0 "

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a68a06eb4d27..83c97626ff7e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7869,15 +7869,6 @@ class DefaultedComparisonAnalyzer
         assert(Best->BuiltinParamTypes[2].isNull() &&
                "invalid builtin comparison");
 
-        // The builtin operator for relational comparisons on function
-        // pointers is the only known case which cannot be used.
-        if (OO != OO_EqualEqual && T->isFunctionPointerType()) {
-          if (Diagnose == ExplainDeleted)
-            S.Diag(Subobj.Loc, 
diag::note_defaulted_comparison_selected_invalid)
-                << Subobj.Kind << Subobj.Decl << T;
-          return Result::deleted();
-        }
-
         if (NeedsDeducing) {
           Optional<ComparisonCategoryType> Cat =
               getComparisonCategoryForBuiltinCmp(T);

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b64335641257..2d0f314f380f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11802,6 +11802,21 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, 
ExprResult &RHS,
                                    LHS.get()->getSourceRange());
   }
 
+  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();
+    if (IsError)
+      return QualType();
+  }
+
   if ((LHSType->isIntegerType() && !LHSIsNull) ||
       (RHSType->isIntegerType() && !RHSIsNull)) {
     // Skip normal pointer conversion checks in this case; we have better
@@ -11869,12 +11884,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, 
ExprResult &RHS,
               << LHSType << RHSType << LCanPointeeTy->isIncompleteType()
               << RCanPointeeTy->isIncompleteType();
         }
-        if (LCanPointeeTy->isFunctionType()) {
-          // Valid unless a relational comparison of function pointers
-          Diag(Loc, 
diag::ext_typecheck_ordered_comparison_of_function_pointers)
-              << LHSType << RHSType << LHS.get()->getSourceRange()
-              << RHS.get()->getSourceRange();
-        }
       }
     } else if (!IsRelational &&
                (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 606cc5698986..8092f0be6cce 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8466,7 +8466,7 @@ class BuiltinOperatorOverloadBuilder {
   //        bool       operator==(T, T);
   //        bool       operator!=(T, T);
   //           R       operator<=>(T, T)
-  void addGenericBinaryPointerOrEnumeralOverloads() {
+  void addGenericBinaryPointerOrEnumeralOverloads(bool IsSpaceship) {
     // 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,6 +8525,8 @@ class BuiltinOperatorOverloadBuilder {
         // Don't add the same builtin candidate twice.
         if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
           continue;
+        if (IsSpaceship && PtrTy->isFunctionPointerType())
+          continue;
 
         QualType ParamTypes[2] = {PtrTy, PtrTy};
         S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
@@ -8715,7 +8717,7 @@ class BuiltinOperatorOverloadBuilder {
   //
   //   where LR is the result of the usual arithmetic conversions
   //   between types L and R.
-  void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
+  void addBinaryBitwiseArithmeticOverloads() {
     if (!HasArithmeticOrEnumeralCandidateType)
       return;
 
@@ -9221,18 +9223,20 @@ void 
Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
   case OO_EqualEqual:
   case OO_ExclaimEqual:
     OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads();
-    LLVM_FALLTHROUGH;
+    
OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false);
+    OpBuilder.addGenericBinaryArithmeticOverloads();
+    break;
 
   case OO_Less:
   case OO_Greater:
   case OO_LessEqual:
   case OO_GreaterEqual:
-    OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+    
OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false);
     OpBuilder.addGenericBinaryArithmeticOverloads();
     break;
 
   case OO_Spaceship:
-    OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+    OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/true);
     OpBuilder.addThreeWayArithmeticOverloads();
     break;
 
@@ -9241,7 +9245,7 @@ void 
Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
   case OO_Pipe:
   case OO_LessLess:
   case OO_GreaterGreater:
-    OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+    OpBuilder.addBinaryBitwiseArithmeticOverloads();
     break;
 
   case OO_Amp: // '&' is either unary or binary
@@ -9251,7 +9255,7 @@ void 
Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
       //      operator '->', the built-in candidates set is empty.
       break;
 
-    OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+    OpBuilder.addBinaryBitwiseArithmeticOverloads();
     break;
 
   case OO_Tilde:

diff  --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp 
b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
index 01fff692c0c8..61d03e0723dc 100644
--- a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -159,7 +159,7 @@ namespace BadDeducedType {
 namespace PR48856 {
   struct A {
     auto operator<=>(const A &) const = default; // expected-warning 
{{implicitly deleted}}
-    void (*x)();                                 // expected-note {{does not 
support relational comparisons}}
+    void (*x)();                                 // expected-note {{because 
there is no viable three-way comparison function for member 'x'}}
   };
 
   struct B {
@@ -192,12 +192,23 @@ namespace PR50591 {
   };
   std::partial_ordering cmp_b2 = b2() <=> b2();
 
+  using fp = void (*)();
+
   struct a3 {
-    using fp = void (*)();
     operator fp() const;
   };
   struct b3 {
     auto operator<=>(b3 const &) const = default; // expected-warning 
{{implicitly deleted}}
-    a3 f; // expected-note {{would compare member 'f' as 'void (*)()', which 
does not support relational comparisons}}
+    a3 f;                                         // expected-note {{because 
there is no viable three-way comparison function}}
+  };
+
+  struct a4 { // Test that function pointer conversion operator here is 
ignored for this overload resolution.
+    operator int() const;
+    operator fp() const;
+  };
+  struct b4 {
+    auto operator<=>(b4 const &) const = default;
+    a4 f;
   };
+  std::strong_ordering cmp_b4 = b4() <=> b4();
 }

diff  --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp
index 8bfa29a8b667..e4f1105ceebe 100644
--- a/clang/test/CXX/drs/dr15xx.cpp
+++ b/clang/test/CXX/drs/dr15xx.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify 
-fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify 
-fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify 
-fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify 
-fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s 
-verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s 
-verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s 
-verify=expected,cxx14_17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s 
-verify=expected,cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
 
 namespace dr1512 { // dr1512: 4
   void f(char *p) {
@@ -28,10 +28,10 @@ namespace dr1512 { // dr1512: 4
   template<typename A, typename B, typename C> void 
composite_pointer_type_is_ord() {
     composite_pointer_type_is_base<A, B, C>();
 
-    typedef __typeof(val<A>() < val<B>()) cmp;
-    typedef __typeof(val<A>() <= val<B>()) cmp;
-    typedef __typeof(val<A>() > val<B>()) cmp;
-    typedef __typeof(val<A>() >= val<B>()) cmp;
+    typedef __typeof(val<A>() < val<B>()) cmp;  // cxx17-warning 2 {{ordered 
comparison of function pointers}}
+    typedef __typeof(val<A>() <= val<B>()) cmp; // cxx17-warning 2 {{ordered 
comparison of function pointers}}
+    typedef __typeof(val<A>() > val<B>()) cmp;  // cxx17-warning 2 {{ordered 
comparison of function pointers}}
+    typedef __typeof(val<A>() >= val<B>()) cmp; // cxx17-warning 2 {{ordered 
comparison of function pointers}}
     typedef bool cmp;
   }
 
@@ -79,8 +79,8 @@ namespace dr1512 { // dr1512: 4
     no_composite_pointer_type<const int (A::*)(), volatile int (C::*)()>();
 
 #if __cplusplus > 201402
-    composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>();
-    composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>();
+    composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>(); 
// expected-note {{requested here}}
+    composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>(); 
// expected-note {{requested here}}
     composite_pointer_type_is_unord<int (A::*)() noexcept, int (A::*)(), int 
(A::*)()>();
     composite_pointer_type_is_unord<int (A::*)(), int (A::*)() noexcept, int 
(A::*)()>();
     // 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
index 5c4c75595817..9c8fe2de2f59 100644
--- a/clang/test/CXX/drs/dr3xx.cpp
+++ b/clang/test/CXX/drs/dr3xx.cpp
@@ -18,9 +18,9 @@ namespace dr301 { // dr301: yes
   void operator-(S, S);
 
   void f() {
-    bool a = (void(*)(S, S))operator+<S> <
+    bool a = (void(*)(S, S))operator+<S> < // expected-warning {{ordered 
comparison of function pointers}}
              (void(*)(S, S))operator+<S>;
-    bool b = (void(*)(S, S))operator- < // cxx20_2b-note {{to match this '<'}}
+    bool b = (void(*)(S, S))operator- < // cxx20_2b-note {{to match this '<'}} 
cxx98_17-warning {{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
index 82c92b77bd17..81efbb0a4727 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -515,6 +515,7 @@ namespace UnspecifiedRelations {
 
   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;
 
   // If two pointers point to non-static data members of the same object with

diff  --git a/clang/test/FixIt/fixit.cpp b/clang/test/FixIt/fixit.cpp
index bfff20e76c14..8a3500c9f210 100644
--- a/clang/test/FixIt/fixit.cpp
+++ b/clang/test/FixIt/fixit.cpp
@@ -1,12 +1,12 @@
-// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable -Wno-comment 
-verify -fcxx-exceptions -x c++ -std=c++98 %s
+// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable -Wno-comment 
-verify -fcxx-exceptions -x c++ -std=c++98 -Wno-c++14-extensions %s
 // RUN: cp %s %t-98
-// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable 
-Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++98 %t-98
-// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Wno-unused-but-set-variable 
-Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++98 %t-98
-// RUN: not %clang_cc1 -fsyntax-only -pedantic -fdiagnostics-parseable-fixits 
-x c++ -std=c++11 %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable -Wno-comment 
-verify -fcxx-exceptions -x c++ -std=c++11 %s
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable 
-Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++98 -Wno-c++14-extensions 
%t-98
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Wno-unused-but-set-variable 
-Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++98 -Wno-c++14-extensions 
%t-98
+// RUN: not %clang_cc1 -fsyntax-only -pedantic -fdiagnostics-parseable-fixits 
-x c++ -std=c++11 -Wno-c++14-extensions %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable -Wno-comment 
-verify -fcxx-exceptions -x c++ -std=c++11 -Wno-c++14-extensions %s
 // RUN: cp %s %t-11
-// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable 
-Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++11 %t-11
-// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Wno-unused-but-set-variable 
-Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++11 %t-11
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-unused-but-set-variable 
-Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++11 -Wno-c++14-extensions 
%t-11
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Wno-unused-but-set-variable 
-Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++11 -Wno-c++14-extensions 
%t-11
 
 /* This is a test of the various code modification hints that are
    provided as part of warning or extension diagnostics. All of the
@@ -292,21 +292,21 @@ namespace greatergreater {
 
   template<template<typename>> struct TemplateTemplateParam; // expected-error 
{{requires 'class'}}
 
-  template<typename T> void t();
+  template <typename T> int t = 0;
   void g() {
-    void (*p)() = &t<int>;
-    (void)(&t<int>==p); // expected-error {{use '> ='}}
-    (void)(&t<int>>=p); // expected-error {{use '> >'}}
+    int p = 0;
+    (void)(t<int>==p); // expected-error {{use '> ='}}
+    (void)(t<int>>=p); // expected-error {{use '> >'}}
 #if __cplusplus < 201103L
-    (void)(&t<S<int>>>=p); // expected-error {{use '> >'}}
-    (Shr)&t<S<int>>>>=p; // expected-error {{use '> >'}}
+    (void)(t<S<int>>>=p); // expected-error {{use '> >'}}
+    (Shr)t<S<int>>>>=p; // expected-error {{use '> >'}}
 #endif
 
-    // FIXME: We correct this to '&t<int> > >= p;' not '&t<int> >>= p;'
-    //(Shr)&t<int>>>=p;
+    // FIXME: We correct this to 't<int> > >= p;' not 't<int> >>= p;'
+    //(Shr)t<int>>>=p;
 
     // FIXME: The fix-its here overlap.
-    //(void)(&t<S<int>>==p);
+    //(void)(t<S<int>>==p);
   }
 }
 

diff  --git a/clang/test/Parser/cxx-template-argument.cpp 
b/clang/test/Parser/cxx-template-argument.cpp
index 0e72cbfbfb17..a42a473409ee 100644
--- a/clang/test/Parser/cxx-template-argument.cpp
+++ b/clang/test/Parser/cxx-template-argument.cpp
@@ -22,15 +22,18 @@ namespace greatergreater {
   void f(S<int>=0); // expected-error {{a space is required between a right 
angle bracket and an equals sign (use '> =')}}
   void f(S<S<int>>=S<int>()); // expected-error {{use '> >'}} expected-error 
{{use '> ='}}
   template<typename T> void t();
+  struct R {
+    friend void operator==(void (*)(), R) {}
+    friend void operator>=(void (*)(), R) {}
+  };
   void g() {
-    void (*p)() = &t<int>;
-    (void)(&t<int>==p); // expected-error {{use '> ='}}
-    (void)(&t<int>>=p); // expected-error {{use '> >'}}
-    (void)(&t<S<int>>>=p);
+    (void)(&t<int>==R()); // expected-error {{use '> ='}}
+    (void)(&t<int>>=R()); // expected-error {{use '> >'}}
+    (void)(&t<S<int>>>=R());
 #if __cplusplus <= 199711L
     // expected-error@-2 {{use '> >'}}
 #endif
-    (void)(&t<S<int>>==p); // expected-error {{use '> >'}} expected-error 
{{use '> ='}}
+    (void)(&t<S<int>>==R()); // expected-error {{use '> >'}} expected-error 
{{use '> ='}}
   }
 }
 

diff  --git a/clang/test/Sema/compare.c b/clang/test/Sema/compare.c
index 85dcffc502fd..6f25eb21ff3c 100644
--- a/clang/test/Sema/compare.c
+++ b/clang/test/Sema/compare.c
@@ -220,7 +220,7 @@ int pointers(int *a) {
 int function_pointers(int (*a)(int), int (*b)(int), void (*c)(int)) {
   return a > b; // expected-warning {{ordered comparison of function pointers}}
   return function_pointers > function_pointers; // expected-warning 
{{self-comparison always evaluates to false}} expected-warning{{ordered 
comparison of function pointers}}
-  return a > c; // expected-warning {{comparison of distinct pointer types}}
+  return a > c;                                 // expected-warning 
{{comparison of distinct pointer types}} expected-warning {{ordered comparison 
of function pointers}}
   return a == (void *) 0;
   return a == (void *) 1; // expected-warning {{equality comparison between 
function pointer and void pointer}}
 }

diff  --git a/clang/test/SemaCXX/compare-cxx2a.cpp 
b/clang/test/SemaCXX/compare-cxx2a.cpp
index a45955418c44..fdeb93153715 100644
--- a/clang/test/SemaCXX/compare-cxx2a.cpp
+++ b/clang/test/SemaCXX/compare-cxx2a.cpp
@@ -212,8 +212,6 @@ struct Class {};
 struct ClassB : Class {};
 struct Class2 {};
 using FnTy = void(int);
-using FnTy2 = long(int);
-using FnTy3 = void(int) noexcept;
 using MemFnTy = void (Class::*)() const;
 using MemDataTy = long(Class::*);
 
@@ -232,11 +230,6 @@ void test_memptr(MemFnTy mf, MemDataTy md) {
   (void)(md <=> md); // expected-error {{invalid operands}} expected-warning 
{{self-comparison}}
 }
 
-void test_compatible_pointer(FnTy *f1, FnTy2 *f2, FnTy3 *f3) {
-  (void)(f1 <=> f2); // expected-error {{distinct pointer types}}
-  (void)(f1 <=> f3); // expected-error {{invalid operands}}
-}
-
 // Test that variable narrowing is deferred for value dependent expressions
 template <int Val>
 auto test_template_overflow() {

diff  --git a/clang/test/SemaCXX/compare-function-pointer.cpp 
b/clang/test/SemaCXX/compare-function-pointer.cpp
new file mode 100644
index 000000000000..0b185ce08f91
--- /dev/null
+++ b/clang/test/SemaCXX/compare-function-pointer.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+using fp0_t = void (*)();
+using fp1_t = int (*)();
+
+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 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}}
+auto tw1 = a <=> c; // expected-error {{ordered comparison of function 
pointers}}

diff  --git a/clang/test/SemaTemplate/resolve-single-template-id.cpp 
b/clang/test/SemaTemplate/resolve-single-template-id.cpp
index 9562845a9a6e..8d7bf0847fb1 100644
--- a/clang/test/SemaTemplate/resolve-single-template-id.cpp
+++ b/clang/test/SemaTemplate/resolve-single-template-id.cpp
@@ -65,12 +65,14 @@ int main()
   void (*u)(int) = oneT<int>;
 
   b = (void (*)()) twoT<int>;
-  
-  one < one; //expected-warning {{self-comparison always evaluates to false}} \
-             //expected-warning {{relational comparison result unused}}        
 
 
-  oneT<int> < oneT<int>;  //expected-warning {{self-comparison always 
evaluates to false}} \
-                          //expected-warning {{relational comparison result 
unused}}
+  one < one; // expected-warning {{self-comparison always evaluates to false}} 
\
+             // expected-warning {{relational comparison result unused}}       
\
+             // expected-warning {{ordered comparison of function pointers}}
+
+  oneT<int> < oneT<int>; // expected-warning {{self-comparison always 
evaluates to false}} \
+                         // expected-warning {{relational comparison result 
unused}}       \
+                         // expected-warning {{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<int> < twoT<int>; //expected-error {{reference to overloaded function 
could not be resolved; did you mean to call it?}} {{cannot resolve overloaded 
function 'twoT' from context}}

diff  --git 
a/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp 
b/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp
index 322a1bad1c99..d301bb5c7838 100644
--- a/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp
+++ b/compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp
@@ -13,6 +13,7 @@
 
 #include <assert.h>
 #include <dlfcn.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -38,10 +39,11 @@ int main(int argc, char **argv) {
 
   // It matters whether the unloaded module has a higher or lower address range
   // than the remaining one. Make sure to test both cases.
+  bool lt = reinterpret_cast<uintptr_t>(bar1) < 
reinterpret_cast<uintptr_t>(bar2);
   if (argc < 2)
-    dlclose(bar1 < bar2 ? handle1 : handle2);
+    dlclose(lt ? handle1 : handle2);
   else
-    dlclose(bar1 < bar2 ? handle2 : handle1);
+    dlclose(lt ? handle2 : handle1);
   return 0;
 }
 #endif


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to