This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGad14b5b008e2: [clang] Stop providing builtin overload 
candidate for relational function… (authored by mizvekov).

Changed prior to commit:
  https://reviews.llvm.org/D104892?vs=354607&id=354612#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104892/new/

https://reviews.llvm.org/D104892

Files:
  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/SemaCXX/compare-function-pointer.cpp
  clang/test/SemaTemplate/resolve-single-template-id.cpp
  compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp

Index: compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp
===================================================================
--- compiler-rt/test/asan/TestCases/Posix/coverage-module-unloaded.cpp
+++ 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 @@
 
   // 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
Index: clang/test/SemaTemplate/resolve-single-template-id.cpp
===================================================================
--- clang/test/SemaTemplate/resolve-single-template-id.cpp
+++ clang/test/SemaTemplate/resolve-single-template-id.cpp
@@ -65,12 +65,14 @@
   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}}
Index: clang/test/SemaCXX/compare-function-pointer.cpp
===================================================================
--- /dev/null
+++ 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}}
Index: clang/test/SemaCXX/compare-cxx2a.cpp
===================================================================
--- clang/test/SemaCXX/compare-cxx2a.cpp
+++ clang/test/SemaCXX/compare-cxx2a.cpp
@@ -212,8 +212,6 @@
 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)(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() {
Index: clang/test/Sema/compare.c
===================================================================
--- clang/test/Sema/compare.c
+++ clang/test/Sema/compare.c
@@ -220,7 +220,7 @@
 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}}
 }
Index: clang/test/Parser/cxx-template-argument.cpp
===================================================================
--- clang/test/Parser/cxx-template-argument.cpp
+++ clang/test/Parser/cxx-template-argument.cpp
@@ -22,15 +22,18 @@
   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 '> ='}}
   }
 }
 
Index: clang/test/FixIt/fixit.cpp
===================================================================
--- clang/test/FixIt/fixit.cpp
+++ 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 @@
 
   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);
   }
 }
 
Index: clang/test/CXX/expr/expr.const/p2-0x.cpp
===================================================================
--- clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -515,6 +515,7 @@
 
   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
Index: clang/test/CXX/drs/dr3xx.cpp
===================================================================
--- clang/test/CXX/drs/dr3xx.cpp
+++ clang/test/CXX/drs/dr3xx.cpp
@@ -18,9 +18,9 @@
   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 '>'}}
Index: clang/test/CXX/drs/dr15xx.cpp
===================================================================
--- clang/test/CXX/drs/dr15xx.cpp
+++ 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 @@
   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 @@
     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::*)()'.
Index: clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
@@ -159,7 +159,7 @@
 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 @@
   };
   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();
 }
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -8466,7 +8466,7 @@
   //        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 @@
         // 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 @@
   //
   //   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 @@
   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 @@
   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 @@
       //      operator '->', the built-in candidates set is empty.
       break;
 
-    OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+    OpBuilder.addBinaryBitwiseArithmeticOverloads();
     break;
 
   case OO_Tilde:
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -11802,6 +11802,21 @@
                                    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 @@
               << 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())) {
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -7869,15 +7869,6 @@
         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);
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6794,9 +6794,14 @@
   "%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 @@
   "%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 "
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -525,6 +525,7 @@
 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">;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D104892: ... Matheus Izvekov via Phabricator via cfe-commits
    • [PATCH] D104... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D104... Matheus Izvekov via Phabricator via cfe-commits
    • [PATCH] D104... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D104... Matheus Izvekov via Phabricator via cfe-commits
    • [PATCH] D104... Matheus Izvekov via Phabricator via cfe-commits

Reply via email to