[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-29 Thread Jens Massberg via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG849b650cf3b6: [clang] Skip defaulted functions in 
zero-as-null-pointer-constant. (authored by massberg).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

Files:
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant 
-std=c++20
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null 
pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // 
expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,12 @@
   CodeSynthesisContext::RewritingOperatorAsSpaceship)
 return;
 
+  // Ignore null pointers in defaulted comparison operators.
+  FunctionDecl *FD = getCurFunctionDecl();
+  if (FD && FD->isDefaulted()) {
+return;
+  }
+
   // If it is a macro from system header, and if the macro name is not "NULL",
   // do not warn.
   SourceLocation MaybeMacroLoc = E->getBeginLoc();


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant -std=c++20
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- 

[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-29 Thread Jens Massberg via Phabricator via cfe-commits
massberg added a comment.

Note: The build failures are in parts of the code that isn't effected by this 
change.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

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


[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-29 Thread Jens Massberg via Phabricator via cfe-commits
massberg marked 2 inline comments as done.
massberg added a comment.

Thanks for the comments!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

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


[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-29 Thread Jens Massberg via Phabricator via cfe-commits
massberg updated this revision to Diff 478477.
massberg added a comment.

Fixed comments and removed unnecessary includes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

Files:
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant 
-std=c++20
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null 
pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // 
expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,12 @@
   CodeSynthesisContext::RewritingOperatorAsSpaceship)
 return;
 
+  // Ignore null pointers in defaulted comparison operators.
+  FunctionDecl *FD = getCurFunctionDecl();
+  if (FD && FD->isDefaulted()) {
+return;
+  }
+
   // If it is a macro from system header, and if the macro name is not "NULL",
   // do not warn.
   SourceLocation MaybeMacroLoc = E->getBeginLoc();


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant -std=c++20
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,12 @@
   

[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-28 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov accepted this revision.
ilya-biryukov added a comment.
This revision is now accepted and ready to land.

LGTM with a few NITs. Thanks!




Comment at: clang/lib/Sema/Sema.cpp:600
 
+  // Ignore null pointers in defaulted functions, e.g. defaulted comparison
+  // operators.

NIT: maybe even shorten to "ignore in defaulted comparison operators"



Comment at: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp:3
+
+#include 
+

NIT: I believe you don't need it as you don't use definitions like `NULL` or 
`SYSTEM_MACRO` from this header.
Similarly, `-isystem %S/Inputs` is not required.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

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


[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-28 Thread Jens Massberg via Phabricator via cfe-commits
massberg updated this revision to Diff 478261.
massberg added a comment.

Run clang-format on changed files.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

Files:
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs 
-Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null 
pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // 
expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,13 @@
   CodeSynthesisContext::RewritingOperatorAsSpaceship)
 return;
 
+  // Ignore null pointers in defaulted functions, e.g. defaulted comparison
+  // operators.
+  FunctionDecl *FD = getCurFunctionDecl();
+  if (FD && FD->isDefaulted()) {
+return;
+  }
+
   // If it is a macro from system header, and if the macro name is not "NULL",
   // do not warn.
   SourceLocation MaybeMacroLoc = E->getBeginLoc();


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs -Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ 

[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-28 Thread Jens Massberg via Phabricator via cfe-commits
massberg updated this revision to Diff 478227.
massberg added a comment.

Sync to head.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138727

Files:
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs 
-Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null 
pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // 
expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,13 @@
   CodeSynthesisContext::RewritingOperatorAsSpaceship)
 return;
 
+  // Ignore null pointers in defaulted functions, e.g. defaulted comparison
+  // operators.
+  FunctionDecl *FD =  getCurFunctionDecl();
+  if (FD && FD->isDefaulted()) {
+return;
+  }
+
   // If it is a macro from system header, and if the macro name is not "NULL",
   // do not warn.
   SourceLocation MaybeMacroLoc = E->getBeginLoc();


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs -Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 

[PATCH] D138727: [clang] Skip defaulted functions in zero-as-null-pointer-constant.

2022-11-25 Thread Jens Massberg via Phabricator via cfe-commits
massberg created this revision.
massberg added a reviewer: ilya-biryukov.
Herald added a project: All.
massberg requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The zero-as-null-pointer-constant check should not fire if it is inside
a defaulted function, e.g. defaulted spaceship operators.
Add C++20 tests with spaceship operators.

Fixes #50221


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138727

Files:
  clang/lib/Sema/Sema.cpp
  clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs 
-Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null 
pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2)); // 
expected-warning{{zero as null pointer constant}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -597,6 +597,13 @@
   CodeSynthesisContext::RewritingOperatorAsSpaceship)
 return;
 
+  // Ignore null pointers in defaulted functions, e.g. defaulted comparison
+  // operators.
+  FunctionDecl *FD =  getCurFunctionDecl();
+  if (FD && FD->isDefaulted()) {
+return;
+  }
+
   // If it is a macro from system header, and if the macro name is not "NULL",
   // do not warn.
   SourceLocation MaybeMacroLoc = E->getBeginLoc();


Index: clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-zero-nullptr-cxx20.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs -Wzero-as-null-pointer-constant -std=c++20
+
+#include 
+
+namespace std {
+class strong_ordering;
+
+// Mock how STD defined unspecified parameters for the operators below.
+struct _CmpUnspecifiedParam {
+  consteval
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
+};
+
+struct strong_ordering {
+  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};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+struct A {
+  int a;
+  constexpr auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  result = (a1 < a2);
+  result = (a1 >= a2);
+  int *ptr = 0; // expected-warning{{zero as null pointer constant}}
+  result = (a1 > (ptr == 0 ? a1 : a2)); // expected-warning{{zero as null pointer constant}}
+  result = (a1 > ((a1 > (ptr == 0 ?