massberg created this revision.
massberg added a reviewer: ilya-biryukov.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
massberg requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

The check has produced false positives when checking the default implementation 
of the spaceship operator.
The default implementation should be skipped by the check.

Modified the existing test so that the check runs into the bug without this fix 
and add another test case.

Fixes #53961


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138701

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
@@ -1,9 +1,32 @@
 // RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
 
 namespace std {
+class strong_ordering;
+
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
 struct strong_ordering {
-  int n;
-  constexpr operator int() const { return n; }
+  signed char value;
+
+  friend constexpr bool operator==(strong_ordering v,
+                                   _CmpUnspecifiedParam) noexcept {
+    return v.value == 0;
+  }
+  friend constexpr bool operator<(strong_ordering v,
+                                  _CmpUnspecifiedParam) noexcept {
+    return v.value < 0;
+  }
+  friend constexpr bool operator>(strong_ordering v,
+                                  _CmpUnspecifiedParam) noexcept {
+    return v.value > 0;
+  }
+  friend constexpr bool operator>=(strong_ordering v,
+                                   _CmpUnspecifiedParam) noexcept {
+    return v.value >= 0;
+  }
   static const strong_ordering equal, greater, less;
 };
 constexpr strong_ordering strong_ordering::equal = {0};
@@ -12,8 +35,10 @@
 } // namespace std
 
 class A {
+  int a;
 public:
   auto operator<=>(const A &other) const = default;
+  // CHECK-FIXES: auto operator<=>(const A &other) const = default;
 };
 
 void test_cxx_rewritten_binary_ops() {
@@ -32,3 +57,14 @@
   result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
   // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : 
a2));
 }
+
+template<class T1, class T2>
+struct P {
+  T1 x1;
+  T2 x2;
+  friend auto operator<=>(const P&, const P&) = default;
+  // CHECK-FIXES: friend auto operator<=>(const P&, const P&) = default;
+};
+
+bool foo(P<int,int> x, P<int, int> y) { return x < y; }
+// CHECK-FIXES: bool foo(P<int,int> x, P<int, int> y) { return x < y; }
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -62,7 +62,8 @@
                         ImplicitCastToNull,
                         hasAncestor(cxxRewrittenBinaryOperator().bind(
                             "checkBinopOperands")))
-                        .bind(CastSequence))))));
+                        .bind(CastSequence))),
+                unless(hasAncestor(functionDecl(isDefaulted()))))));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,


Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
@@ -1,9 +1,32 @@
 // RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
 
 namespace std {
+class strong_ordering;
+
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
 struct strong_ordering {
-  int n;
-  constexpr operator int() const { return n; }
+  signed char value;
+
+  friend constexpr bool operator==(strong_ordering v,
+                                   _CmpUnspecifiedParam) noexcept {
+    return v.value == 0;
+  }
+  friend constexpr bool operator<(strong_ordering v,
+                                  _CmpUnspecifiedParam) noexcept {
+    return v.value < 0;
+  }
+  friend constexpr bool operator>(strong_ordering v,
+                                  _CmpUnspecifiedParam) noexcept {
+    return v.value > 0;
+  }
+  friend constexpr bool operator>=(strong_ordering v,
+                                   _CmpUnspecifiedParam) noexcept {
+    return v.value >= 0;
+  }
   static const strong_ordering equal, greater, less;
 };
 constexpr strong_ordering strong_ordering::equal = {0};
@@ -12,8 +35,10 @@
 } // namespace std
 
 class A {
+  int a;
 public:
   auto operator<=>(const A &other) const = default;
+  // CHECK-FIXES: auto operator<=>(const A &other) const = default;
 };
 
 void test_cxx_rewritten_binary_ops() {
@@ -32,3 +57,14 @@
   result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
   // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : a2));
 }
+
+template<class T1, class T2>
+struct P {
+  T1 x1;
+  T2 x2;
+  friend auto operator<=>(const P&, const P&) = default;
+  // CHECK-FIXES: friend auto operator<=>(const P&, const P&) = default;
+};
+
+bool foo(P<int,int> x, P<int, int> y) { return x < y; }
+// CHECK-FIXES: bool foo(P<int,int> x, P<int, int> y) { return x < y; }
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -62,7 +62,8 @@
                         ImplicitCastToNull,
                         hasAncestor(cxxRewrittenBinaryOperator().bind(
                             "checkBinopOperands")))
-                        .bind(CastSequence))))));
+                        .bind(CastSequence))),
+                unless(hasAncestor(functionDecl(isDefaulted()))))));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to