Disable GCC narrowing conversion errors - c++

I have code from over 20 years in C/C++ and one technique used to handle variable data sizes was to let automatic type conversion handle it.
For example:
#define MY_STATUS_UNDEFINED (-1)
Then if it was compared/used against a int64_t it was auto expanded to -1LL, for uint64_t to 0xFFFFFFFFFFFFFFFF, for uint32_t to 0xFFFFFFFF, int16_t to -1, uint16_t to 0xFFFF, etc..
However, now I'm getting errors with the newer gcc versions that complain about narrowing conversion. In this case it was a switch statement with a UINT variable.
switch (myuint) {
case MY_STATUS_UNDEFINED:
break;
}
What is the recommended way to get it to not error out?
What is the easiest way to get it to not error out?
What is the cleanest way so it doesn't error out and doesn't give any warning message?
Essentially, I want it to do the auto type conversion properly but no warning or errors.

Using the following brief example:
#include <cstdint>
#include <iostream>
#define MY_STATUS_UNDEFINED (-1)
void bar()
{
std::cout << "It works\n";
}
void foo(uint32_t n)
{
switch (n) {
case MY_STATUS_UNDEFINED:
bar();
break;
}
}
int main()
{
foo(0xFFFFFFFF);
return 0;
}
You are seeing the following error from gcc:
error: narrowing conversion of ‘-1’ from ‘int’ to ‘unsigned int’ [-Wnarrowing]
Now, pay careful attention to the error message. gcc is telling the exact option to shut this off. See the [-Wnarrowing] annotation? That's the compilation flag that's responsible for producing this error message.
To turn it off, stick a "no-" in front of it:
-Wno-narrowing
All gcc diagnostics use this convention. Now the shown code will compile, run, and produce the expected result:
It works!
Add -Wno-narrowing to your global compilation options.
You should really consider this to be only a temporary band-aid solution. These compilation errors are exactly what you want. They're telling you about real or potential problems. -Wall -Werror -Wsuggest-override -Wreturn-type are my favorite compilation options.

Related

No warning of loss in precision when implicitly converting from double to int [duplicate]

In the following snippet no warnings are produced. g++4.4.3 -Wall -pedantic
//f is
void f(int );
f(3.14);
double d = 3.14;
int i = d+2;
I have a strong recollection of this being a warning, something along the lines of "Possible loss of precision". Was it removed or is my memory playing tricks on me?
How can i turn this into a warning in g++? I find this a useful warning, or is it a bad idea?
I can't even find anything appropriate at http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Warning-Options.html
$ gcc -Wconversion test.c
test.c: In function ‘main’:
test.c:3: warning: conversion to ‘int’ from ‘double’ may alter its value
Use -Wconversion option. -Wall doesn't include it.
With -Wconversion option, GCC gives these warning messages:
warning: conversion to 'int' alters 'double' constant value
warning: conversion to 'int' from 'double' may alter its value
Apart from what other answers mention it is also worth mentioning that in C++0x {} initialization doesn't narrow. So instead of getting a warning you'll get an error for example
void f(int x)
{
// code
}
int main()
{
f({3.14}); // narrowing conversion of '3.14000000000000012434497875801753252744674682617e+0' from 'double' to 'int' inside { }
}
g++ 4.4 and above support initializer list (with -std=c++0x option)

g++ warning flag to avoid bool to double conversion

I look for a warning compilation flag of g++ that will prevent silent conversion from bool to double.
This answer relates to a broader question of conversion of int to double. The question was dismissed there because it's considered a lossless conversion and perfectly legal.
However, since bool has another semantic meaning than simple integer, I expect that an implicit conversion from bool to double will issue a warning.
I've tried:
-Wall -Wextra -pedantic -Wconversion
on the following code without any success (no warning issued):
#include <iostream>
int foo(double var){
return static_cast<int>(var);
}
int main(){
std::cout << foo(5) << std::endl;
std::cout << foo(5.1) << std::endl;
std::cout << foo(false) << std::endl; // here I want the warning
return 0;
}
I use g++ 4.9.2, but an answer suggesting using higher version is perfectly acceptable.
Thanks.
This is an approach that has nothing to do with gcc, but instead relies on another tool: clang-tidy has a readability-implicit-bool-conversion check that will warn you in this case. You need a separate static analysis check (which might take long to run, depending on your code base), but it works:
clang-tidy --checks=readability-implicit-bool-conversion your-file.cpp
yields
[...] warning: implicit conversion bool -> 'double' [readability-implicit-bool-conversion]
std::cout << foo(false) << std::endl; // here I want the warning
^~~~~
0.0
The real problem is the implicit conversion from bool to int (which is followed by a second conversion to double).
Booleans were added lately to the C++ language and never really considered semantically different from a number (just as there is no true character type).
As there is no narrowing of the type, finding a warning condition is difficult.
If you have the option of turning the bools to a custom class (maybe just temporarily), you can overload the conversion operators.

C++ range for loop, avoiding narrowing error [duplicate]

In the following snippet no warnings are produced. g++4.4.3 -Wall -pedantic
//f is
void f(int );
f(3.14);
double d = 3.14;
int i = d+2;
I have a strong recollection of this being a warning, something along the lines of "Possible loss of precision". Was it removed or is my memory playing tricks on me?
How can i turn this into a warning in g++? I find this a useful warning, or is it a bad idea?
I can't even find anything appropriate at http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Warning-Options.html
$ gcc -Wconversion test.c
test.c: In function ‘main’:
test.c:3: warning: conversion to ‘int’ from ‘double’ may alter its value
Use -Wconversion option. -Wall doesn't include it.
With -Wconversion option, GCC gives these warning messages:
warning: conversion to 'int' alters 'double' constant value
warning: conversion to 'int' from 'double' may alter its value
Apart from what other answers mention it is also worth mentioning that in C++0x {} initialization doesn't narrow. So instead of getting a warning you'll get an error for example
void f(int x)
{
// code
}
int main()
{
f({3.14}); // narrowing conversion of '3.14000000000000012434497875801753252744674682617e+0' from 'double' to 'int' inside { }
}
g++ 4.4 and above support initializer list (with -std=c++0x option)

C++ Type Check in Functions ignored (required double, provided int)

I have the following code
#include <iostream>
using namespace std;
int dmult(int a, int b){
return 2*a*b;
}
int main(void)
{
double a = 3.3;
double b = 2;
int c = dmult(a,b);
cout << c << endl;
return 0;
}
It compiles with MinGW without problems. The result is (as I thought) false. Is it a problem of the compiler that there is no warning, that a function expecting integers, but fed with doubles, can compile without warning even if the input type is wrong? Does it mean that C++ ignores the input type of a function? Shouldn't it realize that the function arguments have the wrong type?
double's are implicitly convertible to ints (and truncated), and the compiler is not forced by the standard to emit a warning (it tries its best to perform the conversion whenever possible). Compile with -Wconversion
g++ -Wconversion program.cpp
and you'll get your warning:
warning: conversion to 'int' from 'double' may alter its value [-Wfloat-conversion]
The typical warning flags -Wall -Wextra don't catch it since many times it is the programmer's intention to truncate double's to int's.
Live example here.
c++ automatically casts floats and doubles to integer literals by truncating them. so 3.3 becomes 3 when you call dmult(3.3,2)

Compiler does not give error when using list initialization which will cause information loss

In c++ primer(5th), it mentioned:
When used with variables of built-in type, this form of initialization
has one
important property: The compiler will not let us list initialize variables of built-in type if the initializer might lead to the loss
of information:
longdouble ld = 3.1415926536;
int a{ld}, b = {ld}; // error: narrowing conversion required
int c(ld), d = ld; // ok: but value will be truncate
I compile the code using gcc4.8.1 , it only give a warning rather than an error.
g++ -W -Wall -Wextra -pedantic -std=c++0x -o m main.cpp
main.cpp: In function ‘int main()’:
main.cpp:64:13: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
^
main.cpp:64:22: warning: narrowing conversion of ‘ld’ from ‘long double’ to ‘int’ inside { } [-Wnarrowing]
int a{ld}, b= {ld};
Is there any flags that will turn on the feature of the important property ?
A quick search for "gcc diagnostic flag" turns up documentation resources.
Inside your program, you could do this:
#ifdef __GNUC__
# pragma GCC diagnostic error "-Wnarrowing"
#endif
There is a command-line option too: -Werror=narrowing, but since you want to alter the semantic meaning of the program itself according to GCC, putting it in the source code is probably more appropriate.
Note, when it makes a difference other than simple well-formedness, such as in overload selection, GCC does diagnose the condition correctly.
The standard never calls for errors or for warnings: the standard only requires an implementation to issue a diagnostic. Whether such a diagnostic takes the form of a compiler error, or a warning, or something entirely different from them both, is outside the scope of the standard.