What is gcc -Wstringop-overflow complaining about here? - c++

The following code (reduced from a larger, more sensible sample):
#include <vector>
void shrink(std::vector<int>& v) {
while (v.size() > 0) {
v.resize(v.size() - 1);
}
}
Leads gcc 7.3 to emit this warning (godbolt):
In function 'void shrink(std::vector<int>&)':
cc1plus: warning: 'void* __builtin_memset(void*, int, long unsigned int)':
specified size 18446744073709551612 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
I have been staring at this code for close to an hour with a colleague, and it just seems correct to me; what is gcc complaining about?

it just seems correct to me
The example is correct.
what is gcc complaining about?
This is a compiler bug. Here is the bugzilla. The bug appears to be fixed in GCC 8.

Related

Disable GCC narrowing conversion errors

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.

Signedness of int in while comparing with string.size() showing warning

So, i was writing down this code
void shortened(string s){
int cnt=0;
for(int i=0;i<s.size()-1;++i){
cnt++;
}
//some extra code
}
this for loop showed me a warning and i.e. of comparison of integer expressions of different signedness int and string::size_type. But as soon as I changed int i = 0 to unsigned int i=0 there was no warning. I know that the length of the string can never be zero and that's why the warning was shown because int i can hold negative numbers as well. But why the warning was being shown in the first place?
i-0;i<s.size()-1
in itself was very complete. I need to clear my doubt.
Assume you are using g++ as compiler. (gcc is the same while clang is unfamiliar to me)
This warning comes from the compilation option -Wall which asks the compiler to give you detailed warning for everything( Wall = Warning All). (For more information, you can visit https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options)
So g++ -o tmp tmp.cpp won't show such warning but g++ -o tmp -Wall tmp.cpp will.
Come back to the main topic: such a wired warning is shown due to the return type for string.size() is size_t and size_t is one of the unsigned types.
On my machine, I find size_t is defined in stddef.h as followed:
#define __SIZE_TYPE__ long unsigned int
typedef __SIZE_TYPE__ size_t;
You compare between an int and an unsigned int in for statement and this why here is such a warning.

How to get the compiler to warn that this is an invalid bool?

We just got burnt by a typo: "constexpr bool maxDistance=10000;"
Both gcc and clang compile this with no warning.
The real error here is that the variable shouldn't have been of type bool, but should have been an integer type instead.
How can we ensure we get a compiler warning in future?
#include <iostream>
constexpr bool number = 1234;
int main(int argc, char* argv[])
{
std::cout << number + 10000 << std::endl; // prints 10001.
return number;
}
The error here is that the variable is declared with the wrong type, however neither clang nor gcc give a warning.
gcc -Wall -std=c++14 test.cpp -lstdc++
clang -Wall -std=c++14 test.cpp -lstdc++
(using gcc 5.4.0 and clang 3.8.0)
Note: I've since learnt about a possible compile flag: -Wint-in-bool-context however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?
You should use direct list initialization syntax, it prohibits narrowing:
constexpr bool number{1234}; // error: narrowing conversion of '1234' from 'int' to 'bool' [-Wnarrowing]
I've discovered that gcc has a flag '-Wint-in-bool-context' however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?

How to silence long long integer constant warning from GCC

I have some code using large integer literals as follows:
if(nanoseconds < 1'000'000'000'000)
This gives the compiler warning integer constant is too large for 'long' type [-Wlong-long]. However, if I change it to:
if(nanoseconds < 1'000'000'000'000ll)
...I instead get the warning use of C++11 long long integer constant [-Wlong-long].
I would like to disable this warning just for this line, but without disabling -Wlong-long or using -Wno-long-long for the entire project. I have tried surrounding it with:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
...
#pragma GCC diagnostic pop
but that does not seem to work here with this warning. Is there something else I can try?
I am building with -std=gnu++1z.
Edit: minimal example for the comments:
#include <iostream>
auto main()->int {
double nanoseconds = 10.0;
if(nanoseconds < 1'000'000'000'000ll) {
std::cout << "hello" << std::endl;
}
return EXIT_SUCCESS;
}
Building with g++ -std=gnu++1z -Wlong-long test.cpp gives test.cpp:6:20: warning: use of C++11 long long integer constant [-Wlong-long]
I should mention this is on a 32bit platform, Windows with MinGW-w64 (gcc 5.1.0) - the first warning does not seem to appear on my 64bit Linux systems, but the second (with the ll suffix) appears on both.
It seems that the C++11 warning when using the ll suffix may be a gcc bug. (Thanks #praetorian)
A workaround (inspired by #nate-eldredge's comment) is to avoid using the literal and have it produced at compile time with constexpr:
int64_t constexpr const trillion = int64_t(1'000'000) * int64_t(1'000'000);
if(nanoseconds < trillion) ...

No warning on assignment of int to short (gcc)

I often use assignment of "longer" typed variables to "shorter" ones, for example int to short or uint32_t to uint8_t. One day i decided to find all such cases in my code using gcc, but found to my amazement that gcc didn't output any warnings!
int long_value;
short short_value;
std::cin >> long_value; // Example input: 32769
short_value = long_value; // MS Visual Studio complains here at warning level 4
std::cout << "Long: " << long_value << '\n'; // My example output: 32769
std::cout << "Short: " << short_value << '\n'; // My example output: -32767
Using gcc -Wall or gcc -Wconversion didn't help (gcc didn't output any warning). Actually, it never output any warning for any input and output type (e.g. long and unsigned char).
I have never found an actual bug in gcc so i am almost sure this behavior has a reason.
So why no warning?
Update: i use gcc 4.1.2.
This feature was added in gcc 4.3 version. Previously this was not available.
I hope you are using gcc version 4.2 or below.
http://gcc.gnu.org/wiki/NewWconversion confirms this.
This bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2707 also talks about it.
I can't reproduce that. Compiling this code with gcc 4.4.5 with -Wconversion, I get
a.cc: In function ‘void f()’:
a.cc:7: warning: conversion to ‘short int’ from ‘int’ may alter its value