Warn about class member self-initialization - c++

Have a look at this piece of C++ code:
class Foo
{
int a;
public: Foo(int b): a(a) {}
};
Obviously, the developer meant to initialize a with b rather than a itself, and this is a pretty hard to spot error.
Clang++ will warn about this possible mistake while GCC won't, even with additional warnings enabled:
$ clang++ -c init.cpp
init.cpp:5:27: warning: field is uninitialized when used here [-Wuninitialized]
public: Foo(int b): a(a) {}
^
$ g++ -Wall -Wuninitialized -Winit-self -c init.cpp
$
Is there any chance of enabling the same output for g++?

Use a newer gcc :-) Seems to work fine for me:
stieber#gatekeeper:~$ g++ -Wall -Wuninitialized -Winit-self -c Test.cpp
Test.cpp: In constructor ‘Foo::Foo(int)’:
Test.cpp:5:9: warning: ‘Foo::a’ is initialized with itself [-Wuninitialized]
stieber#gatekeeper:~$ gcc --version
gcc (Debian 4.7.1-2) 4.7.1

Related

Detecting this undefined behavior in gcc/clang?

I am trying to detect the following undefined behavior:
% cat undef.cxx
#include <iostream>
class C
{
int I;
public:
int getI() { return I; }
};
int main()
{
C c;
std::cout << c.getI() << std::endl;
return 0;
}
For some reason all my naive attempts have failed so far:
% g++ -Wall -pedantic -o undef -fsanitize=undefined undef.cxx && ./undef
21971
same goes for:
% clang++ -Weverything -o undef -fsanitize=undefined undef.cxx && ./undef
0
Is there a way to use a magic flag in gcc/clang to report a warning/error for the above code at compile time ? at run time ?
References:
% g++ --version
g++ (Debian 10.2.1-6) 10.2.1 20210110
and
% clang++ --version
Debian clang version 11.0.1-2
Turns out my g++ version seems to handle it just fine, all I was missing is the optimization flag:
% g++ -O2 -Wall -pedantic -o undef -fsanitize=undefined undef.cxx && ./undef
undef.cxx: In function ‘int main()’:
undef.cxx:7:25: warning: ‘c.C::I’ is used uninitialized in this function [-Wuninitialized]
7 | int getI() { return I; }
| ^
0
This is clearly documented upstream:
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wuninitialized
Because these warnings depend on optimization, the exact variables or
elements for which there are warnings depend on the precise
optimization options and version of GCC used.
Here is upstream 'meta'-bug to track all those related issues:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24639

g++ compile options with -std=c++14 compile error showing Werror=c++11-compat

My environment Arch Linux, gcc 7.2
I'm learning C++ and I'm using keyword constexpr to define a constant, while compile, it give me an error message
error: identifier ‘constexpr’ is a keyword in C++11 [-Werror=c++11-compat]
I can compile my program with default g++, but cannot compile with -std=c++14 and -Werror
The command I'm using is:
g++ -std=c++14 -O2 -Wall -Werror -Wextra -ansi -flto
I believe the -Werror option caused the issue. but what is the issue? can someone tell me please?
#include <iostream>
int main() {
constexpr double yen_dollar = 0.107;
std::cout << yen_dollar << std::endl;
return 0;
}
test.cpp:4:5: error: identifier ‘constexpr’ is a keyword in C++11 [-Werror=c++11-compat]
constexpr double yen_dollar = 0.107;
^~~~~~~~~
test.cpp: In function ‘int main()’:
test.cpp:4:5: error: ‘constexpr’ was not declared in this scope
test.cpp:5:16: error: ‘yen_dollar’ was not declared in this scope
std::cout << yen_dollar << std::endl;
From the GCC documentation §3.4 Options Controlling C Dialect, one can read:
-ansi
In C mode, this is equivalent to -std=c90. In C++ mode, it is equivalent to -std=c++98.
Since, you compiled with
g++ -std=c++14 -O2 -Wall -Werror -Wextra -ansi -flto
-ansi overwrites -std=c++14 with -std=c++98. This is why constexpr is not recognized.
Solution: get rid of the -ansi flag.

Defining a constructor of a class in C++

I am currently going through Bjarne Stroustrup's "The C++ Programming Language (4th Edition)" and am trying to understand whether is the following a syntax error or was it the way I compiled it.
According to the following code snippet (extracted from the book), my constructor should look like this:
class Vector {
public:
Vector(int s): elem{new double[s]}, sz{s} {} // Construct a Vector
...
private:
double* elem; // Pointer to the elements
int sz; // The number of elements
};
But, I am unable to compile it unless I change the following as per the suggestion of the error message:
Vector(int s): elem(new double[s]), sz(s) {}
Note: I compiled my C++ codes using the following command through the Mac Terminal:
g++ -ansi -pedantic -Wall Test.cpp -o Test.o
Thank you in advance.
Probably, all you need to do is to compile it for C++ 11:
g++ -std=c++11 -ansi -pedantic -Wall Test.cpp -o Test.o
As #molbdnilo pointed out in a comment, remove -ansi from the command, because this is a synonym for std=c89 or std=c++98.
g++ -std=c++11 -pedantic -Wall Test.cpp -o Test.o

G++ -Wshadow doesn't warn about static member shadowing

Once again I lost some hours because of mere stupidity which could have been recognized by the compiler. This is the source code in question:
class f {
static int mVar;
int g(int x) { int mVar=3; return x+mVar; }
};
int f::mVar = 1;
The problem is, that I accidentally added int in front of mVar. When I compile this with: g++ -c -Wall -Wextra -Wshadow shadowtest.cpp I don't get any warning, about the local mVar shadowing the static member mVar.
But if I don't declare the member variable to be static, then g++ correctly issues a warning:
class f {
int mVar;
f(int rVar) : mVar(rVar) {};
int g(int x) { int mVar=3; return x+mVar; }
};
compile with g++ -c -Wall -Wextra -Wshadow shadowtest2.cpp gets:
shadowtest2.cpp:5:24: warning: declaration of ‘mVar’ shadows a member of ‘f’ [-Wshadow]
int g(int x) { int mVar=3; return x+mVar; }
^
shadowtest2.cpp:3:9: note: shadowed declaration is here
int mVar;
^
Tested with g++ 4.9.2 and 5.2.1.
Is this correct behavior or a bug? Why?
Edit: I filed a bug report here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68374
Edit 2018-02-12: Doesn't warn in these versions:
g++-4.9 (Debian 4.9.4-2) 4.9.4
g++-5 (Debian 5.4.1-4) 5.4.1 20161202
g++-5 (Debian 5.5.0-8) 5.5.0 20171010
g++-6 (Debian 6.3.0-18) 6.3.0 20170516
g++-6 (Debian 6.4.0-12) 6.4.0 20180123
g++-7 (Debian 7.2.0-16) 7.2.0
g++-7 (Debian 7.3.0-3) 7.3.0
but successfully warns in:
g++-8 (Debian 8-20180207-2) 8.0.1 20180207 (experimental) [trunk revision 257435]
This looks potentially like a bug given the description of -Wshadow in the gcc documentation:
Warn whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C) or whenever a built-in function is shadowed. Note that in C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct/class/enum.
Especially considering that clang warns for this case. This is basically a quality of implementation issue since this is not ill-formed code. I would file a bug report. Most likely they they will provide a rationale for not warning in this case or they will eventually fix the warnings.
It looks like gcc used to warn about this case if we go all the way back to version 4.5.4 see it live.

C++ Move constructor won't compile

I have an unfortunate problem. My GCC 4.6.3 compiler refuses to compile my move constructor.
Exchanging line 6 in the example with "MemoryBlock(const MemoryBlock & other)" would make it compile, but not using the below move constructor declaration. Seems like the compiler does not know C+11, even though it should using 4.6.3. Right?
#include <cstddef>
class MemoryBlock
{
public:
MemoryBlock(MemoryBlock && other) //<----------- RAD 6.
{
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};
int main() {
}
Compiler output:
prog.cpp:6:28: error: expected ‘,’ or ‘...’ before ‘&&’ token
prog.cpp:6:36: error: invalid constructor; you probably meant ‘MemoryBlock (const MemoryBlock&)’
make: * [slask] Error 1
GCC version:
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 (Kör från labbsal i skolan)
makefile:
%.out: %.cpp
g++ -g -W -Wall -std=c++0x $*.cpp -o $*.out;
Try -std=c++11 instead of -std=c++0x. While your compiler knows the usage, the -std=c++0x "turns off" those new rules.