-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Wzero-as-null-pointer-constant warns when using operator<=>
#43670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Retargeting as a libc++ bug. Using a pointer-to-member type here seems like a bad choice. This would probably be better: // Empty struct so not passed at runtime.
struct __zero_type {
// Only accept a constant integer 0 argument.
constexpr __zero_type(int n)
__attribute__((enable_if(n == 0, "comparison only supported with literal 0")))
{}
// Reject any other type; reject int lvalues.
template<typename T> __zero_type(T&&) = delete;
template<typename T> __zero_type(const volatile int&) = delete;
};
// Do not accept class types that convert to int
// (that would require two user-defined conversions).
bool operator<(std::strong_ordering s, __zero_type) This is not quite perfect; we'd accept
If that's a concern, we can certainly add an extension to Clang to do this perfectly. (For example, we could add a built-in |
This one is similar, but has nothing to do with the libc++ implementation? (https://godbolt.org/z/b5fCvj): #include <compare>
class MyStruct {
public:
auto operator<=>(MyStruct const& other) const = default;
};
bool foo(MyStruct bar){
return bar <= bar;
} |
Ah I see, the generated code which uses std::strong_ordering from stdlib just is not visible in the error message. |
The problem might not be in libc++, because
Produces this:
|
It looks like libstdc++ has the same problem as libc++ in this regard. It would certainly seem reasonable to suppress these warnings, since we didn't manage to get the standard libraries fixed in time. :( |
*** Bug llvm/llvm-bugzilla-archive#46803 has been marked as a duplicate of this bug. *** |
CC rtrieu, who was looking at this in the context of the duplicate bug. We probably track some state in Sema to disable this warning while building a <=> operator. Alternatively, we could hard-code knowledge of the exact type names used here by libc++ and libstdc++, but I think similar patterns are likely to emerge for user-authored comparison category types, so the more general approach seems preferable. |
As more data: for clang-cl, Microsoft's implementation just uses a type alias for decltype(nullptr) (distinct from std::nullptr_t) to handle this: |
Here is an example that might also relate to this: std::vector<int> v{1,2,1,2,1,2};
for (auto it = v.cbegin(); (it = find_if(it, v.cend(), somePredicate)) < v.cend(); ++it) {
std::cout << *it << std::endl;
} |
*** Bug llvm/llvm-bugzilla-archive#48281 has been marked as a duplicate of this bug. *** |
Btw., in Visual Studio 16.8, this also happens with clang-cl. In my opinion, this is a really a C++ language defect, as std::strong_ordering etc. must be comparable with literal 0, but there is no way to cleanly implement that, because literal zero doesn't have its own type. So standard libraries are pretty much forced to implement this by interpreting the zero as a pointer. Given that, I think it would be justifiable just to suppress the warning for the special cases where the C++ standard requires comparison a literal zero. We know the implementations pretty much have no choice but to do this, and we know that the code is correct. I would suggest simple suppressing the warning for the comparison operators of std::strong_ordering, std::weak_ordering, and std::partial_ordering. And if users need to define their own categories, they can alwys wrap them in pragmas to disable the warning as well. |
Should this issue really be classified as an enhancement? It makes -Wzero-as-null-pointer-constant completely unusable. You can't even compare two std::strings without triggering the warning. What good is a warning that flags the
Compiled with -std=c++20 -Wzero-as-null-pointer-constant under Ubuntu 20.04 on amd64 WSL with: clang-11 version 1:11.0.1~++20201121072613+973b95e0a84-1 |
*** Bug llvm/llvm-bugzilla-archive#49008 has been marked as a duplicate of this bug. *** |
Fixed for trunk and Clang 12 release branch. |
My test case still triggers the warning with libc++ and libstdc++ as of 3e1317f. Has the fix landed in trunk? |
Yes, but the fix doesn't fix that case. (Ironic, given that's comment#0 of this bug.) We no longer warn when a comparison against a 0 literal is generated by rewriting some other comparison operator in terms of <=> (eg, comment#2, comment#4, comment#9, comment#12), but we still warn for a direct comparison of 0 against a comparison category (or anything else) where the comparison operator takes a pointer type. It's not clear to me what we can do to suppress the remaining warnings -- I don't really want to hardcode the three comparison category types and leave user code to fend for itself, and asking for source-level annotations would be non-portable (and we'd still need to hardcode the standard comparison categories, because libstdc++ and the MS STL won't have our annotations). Hm, I suppose we could decide that a type T is a comparison category type if ADL with T as an associated class finds an 'operator<=>' that returns T, and suppress the warning if so. |
mentioned in issue llvm/llvm-bugzilla-archive#46803 |
mentioned in issue llvm/llvm-bugzilla-archive#48281 |
mentioned in issue llvm/llvm-bugzilla-archive#49008 |
mentioned in issue llvm/llvm-bugzilla-archive#50877 |
In Clang 14.0.1 I'm getting this without an explicit comparison against 0, using an auto-generated operator<=>:
This code doesn't have any explicit 0 checks in it, it's all in the autogenerated code (here's a compiler explorer link, if that helps: I ended up working around it by writing a custom <=> (that just returns (t <=> other.t)) and then a default operator==, which works but definitely isn't ideal. |
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
* build: `17` -> `20` * fix: c++20 complaints Co-authored-by: AngelicosPhosphoros <[email protected]> * fix: incomplete achievement_requirement * refactor: move member function of point to cpp * fix: remove user defined copy constructor error: definition of implicit copy assignment operator for 'point_with_value' is deprecated because it has a user-declared copy constructor [-Werror,-Wdeprecated-copy] * build: disable zero-as-null-pointer-constant cannot use spaceship operator until llvm/llvm-project#43670 * feat: utility concepts header for storing useful concepts related headers * refactor: overhaul `units_def.h` 1. uses `Arithmatic` concepts to ensure they're numbers. 2. uses spaceship operator for comparison. 3. uses auto and arrow returns to make templates readable. 4. make fabs and fmod constexpr. * style: astyle * ci: bumb android jdk to 17 * ci: bump lit version to c++20 * ci: bump gradle version --------- Co-authored-by: AngelicosPhosphoros <[email protected]>
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
It's unfortunate that we need to either accept |
I tested this with clang-tidy-18 recently and it didn't issue a diagnostic about this. Can you test with clang-18? |
The warning is still triggered with options |
Issue llvm#43670 describes a situation where the following comparison will issue a warning when -Wzero-as-null-pointer-constant is enabled: #include <compare> auto b = (1 <=> 2) < 0; This code uses operator<(strong_ordering, Unspecified), which is specified by the Standard to only work with a literal 0. In the library, this is achieved by constructing Unspecified from a pointer, which works but has the downside of triggering the warning. This patch uses an alternative implementation where we require that the operator is used exactly with an int of value 0 (known at compile-time), however that value can technically be an expression like `1 - 1`, which makes us a bit less strict than what's specified in the Standard. Fixes llvm#43670
Issue llvm#43670 describes a situation where the following comparison will issue a warning when -Wzero-as-null-pointer-constant is enabled: #include <compare> auto b = (1 <=> 2) < 0; This code uses operator<(strong_ordering, Unspecified), which is specified by the Standard to only work with a literal 0. In the library, this is achieved by constructing Unspecified from a pointer, which works but has the downside of triggering the warning. This patch uses an alternative implementation where we require that the operator is used exactly with an int of value 0 (known at compile-time), however that value can technically be an expression like `1 - 1`, which makes us a bit less strict than what's specified in the Standard. Fixes llvm#43670
Issue llvm#43670 describes a situation where the following comparison will issue a warning when -Wzero-as-null-pointer-constant is enabled: #include <compare> auto b = (1 <=> 2) < 0; This code uses operator<(strong_ordering, Unspecified), which is specified by the Standard to only work with a literal 0. In the library, this is achieved by constructing Unspecified from a pointer, which works but has the downside of triggering the warning. This patch uses an alternative implementation where we require that the operator is used exactly with an int of value 0 (known at compile-time), however that value can technically be an expression like `1 - 1`, which makes us a bit less strict than what's specified in the Standard. Fixes llvm#43670
…9465) Issue llvm#43670 describes a situation where the following comparison will issue a warning when -Wzero-as-null-pointer-constant is enabled: #include <compare> auto b = (1 <=> 2) < 0; This code uses operator<(strong_ordering, Unspecified), which is specified by the Standard to only work with a literal 0. In the library, this is achieved by constructing Unspecified from a pointer, which works but has the downside of triggering the warning. This patch uses an alternative implementation where we require that the operator is used exactly with an int of value 0 (known at compile-time), however that value can technically be an expression like `1 - 1`, which makes us a bit less strict than what's specified in the Standard. Fixes llvm#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
cannot use spaceship operator until llvm/llvm-project#43670
* build: `17` -> `20` * fix: c++20 complaints also 1) fix incomplete achievement_requirement 2) remove user defined copy constructor: error: definition of implicit copy assignment operator for 'point_with_value' is deprecated because it has a user-declared copy constructor [-Werror,-Wdeprecated-copy] Co-authored-by: AngelicosPhosphoros <[email protected]> * build: disable zero-as-null-pointer-constant cannot use spaceship operator until llvm/llvm-project#43670 * refactor: overhaul `units_def.h` 1. add `concepts_utility.h` for storing useful concepts related headers. 2. uses `Arithmatic` concepts to ensure they're numbers. 3. uses spaceship operator for comparison. 4. uses auto and arrow returns to make templates readable. 5. make fabs and fmod constexpr. Co-authored-by: Coolthulhu <[email protected]> * ci: bump lit version to c++20 * refactor: use default equality * ci: explicitly use C++20 for clang-tidy * build: add c++20 flag to `Android.mk` * build: ignore `modernize-use-nullptr` it works as a false positive on spaceship operators `<=>` * refactor: apply some idea suggestions * ci: bump java langauge version to 11 * test: run all clang-tidy check even if it fails * test: problemetic checks * fix: attempt to fix MSVC build error * fix: rollback to old filesystem code passing string directly borks filesystem test on windows * fix: use relative import to prevent clang-tidy complaints * test: add more captures like what's the problem * test: skip `remove_tree` and `remove_directory` test atm rationale: - spent past 6 hours trying to fix this and failed - currently not worth the effort considering it's not used anywhere in-game --------- Co-authored-by: AngelicosPhosphoros <[email protected]> Co-authored-by: Coolthulhu <[email protected]>
Extended Description
Outputs:
See it live: https://godbolt.org/z/9a8cnD
Technically, the warning is accurate. User code has a literal
0
that is being passed to a function accepting anullptr
. However, this is an implementation detail of the standard library and the intended interface for use (users should not usenullptr
there), so we should not warn users for doing so (and definitely should not direct them to change their code).The text was updated successfully, but these errors were encountered: