Warnings on sign conversion when assigning from the result of unsigned division - c++

I compiled the following code with -Wsign-conversion :
int main()
{
unsigned int a = 8;
int b = a + 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int c = a - 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int d = a * 8u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
int e = a / 8u; // gcc warns, but no warning in clang
}
Clang doesn't emit a warning when assigning from the result of an unsigned division, but gcc does.
Why is there a difference in this one particular case?

Clang is just being an extra bit clever: division of an unsigned integer by an unsigned integer larger or equal to 2 means the unsigned integer result will always fit in the signed integer counterpart (to that of the numerator type in the division expression). However, if you divide by an unsigned integer valued 1, the result is no longer guaranteed to fit in a signed integer counterpart, and Clang does emit a warning:
#include <cstdint>
int main() {
uint8_t a = 240; // '240 / 1' will not fit in int8_t
int8_t e = a / 2u; // No warning in clang
int8_t f = a / 1u; // warning: implicit conversion changes signedness: 'unsigned int' to 'int8_t' (aka 'signed char') [-Wsign-conversion]
}
One could also argue that Clang should be able to omit the warning for the similar special case of multiplication by 0; however Clang does not whereas GCC, instead, does:
// Clang warns, no warning in GCC.
int8_t g = a * 0u;
So peculiarly Clang is clever, in this context, w.r.t. division and GCC w.r.t. multiplication.
Finally, note that the gating for Clang to emit this warning during division seems to be only when dividing by 1, as you will not get the same -Wsign-conversion if you divide by 0u; arguably as it has been overridden by the more relevant (in such a context) -Wdivision-by-zero warning:
int8_t h = a / 0u;
warning: division by zero is undefined [-Wdivision-by-zero]

Related

Gcc compiler suppress comparison warning

I getting below warning. How to suppress this warning?
Warning:
warning: comparison of integer expressions of different signedness: 'DWORD' {aka 'unsigned int'} and 'int' [-Wsign-compare]
Code:
DWORD exp = GetExp();
int amount = 20;
if (amount < 0 && exp < -amount)
{
...
}
If you really want to suppress it (it's not recommended, there is a reason a warning is shown, and you should instead eliminate the reason), you can do it by adding -Wno-sign-compare to the gcc command line.

Enable conversion between 64 bit integer types

Trying to port some Windows C++ code to Linux + clang.
Here’s a function:
inline __m256i XM_CALLCONV maskload_epi64( const int64_t *mem_addr, __m256i mask )
{
return _mm256_maskload_epi64( mem_addr, mask );
}
Here’s a compiler output:
no matching function for call to '_mm256_maskload_epi64'
return _mm256_maskload_epi64( mem_addr, mask );
^~~~~~~~~~~~~~~~~~~~~
/usr/include/clang/4.0.0/include/avx2intrin.h:989:1: note: candidate function
not viable: no known conversion from 'const int64_t *'
(aka 'const long *') to 'const long long *' for 1st argument
_mm256_maskload_epi64(long long const *__X, __m256i __M)
Is there a compiler switch to make it cast between different 64 bit built-in types without errors?

C++ / OpenGL: Texture to pixmap example - narrowing conversion error

I am trying to run this texture to pixmap example from OpenGL and get the following error
tex_to_pix.cpp:40:1: error: narrowing conversion of ‘4294967295u’ from ‘unsigned int’ to ‘int’ inside { } [-Wnarrowing]
The error refers to the following code block of the example:
const int pixmap_config[] = {
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_DOUBLEBUFFER, False,
GLX_Y_INVERTED_EXT, GLX_DONT_CARE,
None
};
What is the reason for this error?
Is it a compiler or c++11 problem?
Is there a way i can either make my compiler ignore -Wnarrowing or make a safe conversion?
The issue is with GLX_DONT_CARE which is defined as:
#define GLX_DONT_CARE 0xFFFFFFFF
Because this value does not fit into a 32-bit int, its type is unsigned int (see this answer). The rules for narrowing conversion were indeed changed in c++11.
Trying to implicitly convert this unsigned int into an int causes the narrowing conversion warning. As shown in this answer, the narrowing problem can be fixed by using static_cast(GLX_DONT_CARE & 0xFFFFFFFF) instead of GLX_DONT_CARE
const int pixmap_config[] = {
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_DOUBLEBUFFER, False,
GLX_Y_INVERTED_EXT, static_cast<int>(GLX_DONT_CARE & 0xFFFFFFFF),
None
};
Alternatively, disable narrowing conversion errors in your compiler (unspecified).

c++ float vector does not recognize float number? [duplicate]

Check out this simple program:
int main() {
float f2 = 7.2; // OK, with warning
float f3 = 7.199999809265137; // OK, no warning
float f4{ 7.2 }; // Fails
float f5{ 7.199999809265137 }; // OK, no warning
float f6 = { 7.2 }; // Fails
float f7 = { 7.199999809265137 }; // OK, no warning
}
When compiled with MSVC 2015 using the default options (cl /W4, version 19.00.23918), I get the following messages:
FloatTest.cpp(2): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(4): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(4): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(6): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(6): warning C4305: 'initializing': truncation from 'double' to 'float'
This program compiles fine with Clang 3.0-3.8 and GCC 4.5.4-6.1.0 (tested with http://melpon.org/wandbox), with only warnings for unused variables. Further, removing/commenting out lines f4 and f6 result in successful compilation (with only the one warning for line f2).
Initially it looks like MSVC is just telling me that 7.2 can't be represented precisely as a float, so it's a narrowing conversion (which is illegal in brace initialization). However, the standard (draft N3337), section 8.5.4, note 7, says this:
A narrowing conversion is an implicit conversion...
from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly)
Emphasis mine. Since 7.2 is within the range of values representable by float, its conversion to float should not be a narrowing conversion according to the standard. Is MSVC in the wrong here, and should I file a bug?
It looks like a bug, indeed. For a workaround, the following appears to silence both errors and warnings in MSVC 2015.
#pragma float_control(precise, off, push)
float f2 = 7.2; // OK, with warning
//...
#pragma float_control(precise, pop)
The same works globally if using the /fp:fast compiler switch, though that one is incompatible with /Za which disables MS language extensions.
Some floating point numbers can be exactly expressed in a float representation and some can't. If the number can be represented in the form x / 2^y where x is any integer and y is an integer 23 or less, it fits. Most decimal numbers can't be represented in this way, as a binary number they repeat forever. 7.2 is one example.
You can fix this easily by appending f to each number, to indicate to the compiler that this is a float constant rather than a double.
float f4{ 7.2f };

no warnings in QT creator

I can't see almost any warnings in my program.
My cpp file:
#include <iostream>
using namespace std;
int main()
{
long long int ll = 100000000067;
unsigned short sh = ll; //no warning here, why?
cout << sh << " " << ll << endl;
int s; //warning only here: warning: unused variable ‘s’ [-Wunused-variable]
return 0;
}
My pro file:
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
QMAKE_CXXFLAGS += -Wall -Wextra -pedantic
I try use project with cmake, but the results are this same.
According to GCC documentation
-Wconversion
Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like abs (x) when x is double; conversions between signed and unsigned, like unsigned ui = -1; and conversions to smaller types, like sqrtf (M_PI). Do not warn for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if the value is not changed by the conversion like in abs (2.0). Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion.
For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.
For me your example with -Wconversion generates
~/main.cpp:9: warning: conversion to 'short unsigned int' from 'long long int' may alter its value [-Wconversion]
unsigned short sh = ll; //no warning here, why?
^