- edited description
[MSVC++] [C4146]: unary minus operator applied to unsigned type, result still unsigned
When using template methods (e.g., blaze::submatrix
) using size_t(-SIMDSIZE)
(with SIMDSIZE
an unsigned integral type), the Microsoft Visual C++ compiler (/std::c++latest /permissive-) reports a C4146, which is a level W2 warning, and fails compilation.
unsigned int i(-1);
unsigned int j(-2);
unsigned int k(-(1u)); // C4146
unsigned int l(-(2u)); // C4146
A simple workaround consist of changing size_t(-SIMDSIZE)
to size_t(0-SIMDSIZE)
.
Comments (11)
-
reporter -
Hi Matthias!
Thanks for creating this issue. We are aware of the problem, but consider this an issue of the MSVC compiler. According to the C++ standard (see [basic.fundamental], note 2), “The range of representable values for the unsigned type is 0 to 2N − 1 (inclusive); arithmetic for the unsigned type is performed modulo 2N . [Note: Unsigned arithmetic does not overflow. Overflow for signed arithmetic yields undefined behavior (7.1). —end note]“. This means that the expression
size_t(-SIMDSIZE)
is well defined according to the C++ standard. Also, the description and example in C4146 is clearly about a different problem that involved signed integral literals and thus does not fit the expression used in Blaze.Still, we’ll try to circumvent the problem by coming up with a working expression for MSVC. Until we come up with a solution, please explicitly disable the warning for Blaze by means of
\wd4146
. Thanks again,Best regards,
Klaus!
-
reporter Ok will forward to the MSVC++ compiler team
-
reporter - changed status to on hold
-
Hi Matthias!
Could you please share a link to the issue for the MSVC compiler team? Thanks a lot,
Best regards,
Klaus!
-
reporter My apologies was still on my backlog: https://developercommunity.visualstudio.com/content/problem/884520/c4146-unary-minus-operator-applied-to-unsigned-typ.html
-
Hi Matthias!
Thanks for creating the issue at the Microsoft developer community. I analysed the problem and compared compiler behavior by means of Compiler Explorer:
int main() { size_t i; std::cin >> i; // Runtime value constexpr size_t N( 4UL ); // Compile time value //const size_t res = i - ( i % N ); // (1) const size_t res = i & (-N); // (2) std::cout << res; }
Both GCC and Clang treat lines
(1)
and(2)
equally and resolve it to a singleand
statement with-4
. MSVC does the same for line(2)
(without warning), but compiles line(1)
into anand
statement with3
, followed by asubtraction
. Based on the standard specification, this may be a missed optimization opportunity.Best regards,
Klaus!
-
reporter I noticed that the /sdl compiler flag is the actual culprit treating that specific warning as an error. No idea what the underlying motivation is to do so.
-
-
assigned issue to
-
assigned issue to
-
- changed status to open
-
- changed status to resolved
Commit 3f637a3 resolves all MSVC C4146 warnings. The fix is immediately available via cloning the Blaze repository and will be officially released in Blaze 3.7.
- Log in to comment