Consider the following code:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> v{{1, 2, 3}};
int a;
std::cout << a << std::endl; // 1
for (const int x : v) {
a = std::max(a, x); // 2
}
std::cout << a << std::endl;
return 0;
}
As modern compilers grew and now keep a watchful eye over dumb programmer mistakes, they track unitialized variables. This C++ code however, confuses them. So far, I get following results:
(1) (2)
g++ 5.3.1
clang++ 3.7 ✔
Solaris Studio 12.5 ✔
As you can see, CLang and solstudio can detect only case (1) and ignore case (2), while g++ is ignoring both. Is there a complication to detect it in case (2)? Why g++ is so bad at this?
Compiler options I used:
$ g++-5 -std=c++11 -Wall -Wpedantic -pedantic -Wextra \
-Wuninitialized -Wmaybe-uninitialized aisa.cpp
$ clang++ -std=c++11 -Wall -Wpedantic -pedantic -Wextra -Wuninitialized aisa.cpp
$ CC -std=c++11 -xprevise aisa.cpp
std::max
takes its arguments by const &
, while the streaming operator <<
for int
s takes the int
by value. Passing an uninitialised object by reference is legal: for example, if the function just takes its address, all is well. Therefore, warning on passing a
to std::max
could easily be a false positive.
First of all: Both compilers only diagnose the first offense, that is they only report the first uninitialized use of a
. So to get a warning for the second one, we need to remove that first line:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> v{{1, 2, 3}};
int a;
for (const int x : v) {
a = std::max(a, x); // 2
}
std::cout << a << std::endl;
return 0;
}
Now we see two unrelated compiler quirks: clang does not include -Wconditional-uninitialized
in -Wall
and -Wextra
. If you enable that, you do get a warning at the std::cout
because it potentially prints an uninitialized variable.
gcc on the other hand only tracks uninitialized variables when the optimizer is enabled, probably to speed up compilation of debug builds. With -O2 -Wall
, gcc 6 throws a warning in both cases, though without pinpointing the location as exactly as clang does in the second case. (gcc <= 5.3 does not warn about the second case as you observed, so it seems that was implemented recently.)
So TL;DR: You did not invoke your compilers right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With