[PATCH] D95409: [clang] implicitly delete space ship operator with function pointers

Matheus Izvekov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 26 13:22:33 PST 2021


mizvekov updated this revision to Diff 319400.
mizvekov added a comment.

added tests

adds test that will catch original bug
also adds some tests on default equality/relational operators

this last one would have caught the issue of not accepting equality
operator for function pointers, had I not remembered about it :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D95409

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p6.cpp
  clang/test/CXX/class/class.compare/class.spaceship/p4.cpp


Index: clang/test/CXX/class/class.compare/class.spaceship/p4.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/class/class.compare/class.spaceship/p4.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+namespace std {
+class partial_ordering {
+  int n;
+  constexpr partial_ordering(int n) : n(n) {}
+
+public:
+  static const partial_ordering less, equivalent, greater, unordered;
+  bool operator!=(int) { return n != 0; }
+};
+constexpr partial_ordering partial_ordering::less{-1},
+    partial_ordering::equivalent{0}, partial_ordering::greater{1},
+    partial_ordering::unordered{2};
+} // namespace std
+
+struct A {
+  auto operator<=>(A const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}}
+  const int &a = 0;                            // expected-note {{defaulted 'operator<=>' is implicitly deleted because class 'A' has a reference member}}
+};
+
+struct B {
+  auto operator<=>(B const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}}
+  void (*a)();                                 // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}}
+};
+
+struct C {
+  auto operator<=>(C const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}}
+  void (C::*a)();                              // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}}
+};
+
+struct D {
+  auto operator<=>(D const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}}
+  int D::*a;                                   // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}}
+};
Index: clang/test/CXX/class/class.compare/class.compare.default/p6.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/class/class.compare/class.compare.default/p6.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+struct A {
+  bool operator==(A const &) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}}
+  bool operator<(A const &) const = default;  // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  // expected-note at -1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}}
+  const int &a = 0; // expected-note {{defaulted 'operator==' is implicitly deleted because class 'A' has a reference member}}
+};
+
+struct B {
+  bool operator==(B const &) const = default;
+  bool operator<(B const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  // expected-note at -1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}}
+  void (*a)();
+};
+
+struct C {
+  bool operator==(C const &) const = default;
+  bool operator<(C const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  // expected-note at -1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}}
+  void (C::*a)();
+};
+
+struct D {
+  bool operator==(D const &) const = default;
+  bool operator<(D const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}}
+  // expected-note at -1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}}
+  int D::*a;
+};
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -7677,7 +7677,8 @@
 
     if (Args[0]->getType()->isOverloadableType())
       S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
-    else {
+    else if (OO == OO_EqualEqual ||
+             !Args[0]->getType()->isFunctionPointerType()) {
       // FIXME: We determine whether this is a valid expression by checking to
       // see if there's a viable builtin operator candidate for it. That isn't
       // really what the rules ask us to do, but should give the right results.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D95409.319400.patch
Type: text/x-patch
Size: 4545 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210126/40f6a48e/attachment-0001.bin>


More information about the cfe-commits mailing list