No warning on assignment of int to short (gcc) - c++

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

Related

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?

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.

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) ...

Runtime error for CLang compiled program (Mac) reading double type with std::cin

I'm pretty new to C++ and working through some examples of the book "Programming Principles and Practices Using C++" (2nd Edition). I wrote the following simple Program (in file Main.cpp):
#include <iostream>
#include <string>
int main () {
double d = 0;
std::string s = "";
while (std::cin >> d >> s) {
std::cout << "--" << d << " " << s << "\n";
}
std::cout << "FATAL? "<< d << " " << u << "\n";
}
Compiling the program (on the command line) with CLang (Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Target: x86_64-apple-darwin13.2.0 Thread model: posix):
clang++ -o Main -std=c++11 -stdlib=libc++ Main.cpp
works fine without any errors. However, when I run the program it behaves strange. I tested the following input:
123m
which results in
--123 m
which is fine (the same holds for entering 123 m). But, entering the following:
123a
results in:
FATAL? 0 m
The same happens for most other characters (e.g. b, c, ...). Entering 123 a works fine though (output: --123 a).
Using GNU g++ works on the other hand. Further, the problem does not come up on a Linux machine compiling the same program with CLang.
As stated before, I'm new to C++ and this seems to be a Mac OS X specific problem. Is this a bug in the Mac CLang implementation or am I doing something seriously wrong here :(?
Thanks in advance!
Ok, I found a solution to the problem in this question asked: CGAL: How can I successfully compile and link CGAL examples (on Mac OS X 10.9 Mavericks)
Compiling with clang++ as follows:
clang++ -o Main -std=c++11 -stdlib=libstdc++ Main.cpp
instead of:
clang++ -o Main -std=c++11 -stdlib=libc++ Main.cpp
solved the problem.
Anyway, as libc++ should be the preferred library to use with clang++ (as I just was told offline) I think it's time for a bug report.
std::basic_istream::operator>> calls std::num_get::get to extract the value from input. Until C++11, the behaviour of std::num_get::get was like that of scanf with the appropriate formatting string. C++11 onwards, std::num_get::get ends up calling strto* functions, which have a more flexible matching than the one based on scanf. In your example, 123[a-f] get interpreted as hex. Since all the input has been consumed by >>d, the >>s part of while(std::cin >> d >> s) leads to the parse failing.

Why are std::stoi and std::array not compiling with g++ c++11?

I've been learning C++ and using the Terminal for the last couple of months. My code was compiling and running fine using g++ and C++11, but in the last couple of days it started giving errors and I have had problems compiling since. The only programs I can compile and run depend on older C++ standards.
The errors I first got related to #include < array > in the header file. Not sure why this happened, but I got around it by using boost/array instead. Another error I can't solve is with std::stoi. Both array and stoi should be in the C++11 standard library. I made the following simple code to demonstrate what's going on:
//
// stoi_test.cpp
//
// Created by ecg
//
#include <iostream>
#include <string> // stoi should be in here
int main() {
std::string test = "12345";
int myint = std::stoi(test); // using stoi, specifying in standard library
std::cout << myint << '\n'; // printing the integer
return(0);
}
Try to compile using ecg$ g++ -o stoi_trial stoi_trial.cpp -std=c++11
array.cpp:13:22: error: no member named 'stoi' in namespace 'std'; did you mean
'atoi'?
int myint = std::stoi(test);
~~~~~^~~~
atoi
/usr/include/stdlib.h:149:6: note: 'atoi' declared here
int atoi(const char *);
^
array.cpp:13:27: error: no viable conversion from 'std::string' (aka
'basic_string') to 'const char *'
int myint = std::stoi(test);
^~~~
/usr/include/stdlib.h:149:23: note: passing argument to parameter here
int atoi(const char *);
^
2 errors generated.
I also get these errors at compilation when using gcc or clang++ and with -std=gnu++11 (I guess they all depend on the same file structure). I also get the same error whether I specify std:: in the code, or if I specify using namespace std;
I worry that these issues arose because of the September Command Line Tools update via Xcode or because I installed boost and this somehow messed up my C++11 libraries. Hopefully there is a simple solution.
My system:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-> dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
Thanks for any insight you can offer.
clang has a weird stdlib, you need to add the following flag when you compile
-stdlib=libc++
your snippet works on my mac with
g++ -std=gnu++11 -stdlib=libc++ test.cpp -o test
This answer describes the problem