https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to M Welinder from comment #0) > The standard is crazy-strict here. Anything other than a literal 0 is > undefined behaviour. Allowed: 0, 0LL, 0'0'0'0, 0x0. I don't think 0LL is allowed. A literal 0 has type int, and 0LL doesn't. I'm unsure about 0'0 and 0x0. > No good: +0, nullptr, > (void*)0, 0+0, '\0', (0,nullptr). gcc incorrectly allows nullptr and > (0,nullptr), but rejects the others. gcc is not incorrect, the code that uses nullptr or (0, nullptr) is incorrect. No diagnostic is required for violations of that rule. > The library tries to do that with a construct that mainly allows null > pointer constants. That leads to the warning when you actually supply the 0 > you are supposed to. > > Suggestion: just use an int argument. That's wrong in different ways (and > might cause warnings with 0LL which is allowed), but it matches 0 better. Using int would allow 1 and 100 though. That seems much worse than allowing other spellings of zero. However, since I added the <compare> header gcc gained support for consteval functions, which would allow us to reject non-zero values. Something like this should work: struct __unspec { template<same_as<int> _Tp> consteval __unspec(_Tp __z) noexcept { if (__z != 0) throw; // comparison category types only compare to 0 } }; This results in errors like: cmp.cc:6:13: error: no match for 'operator<' (operand types are 'std::partial_ordering' and 'long int') 6 | return po < 0L; | ~~ ^ ~~ | | | | | long int | std::partial_ordering and: /home/jwakely/gcc/14/include/c++/14.0.0/compare:59:25: error: expression '<throw-expression>' is not a constant expression 59 | if (__z != 0) throw; // comparison category types only compare to 0 | ^~~~~