After a debug session I realised that the next sample code compile with no warnings (g++-4.7.2 -Wextra and -Wall)
char *p;
char *q = std::move(p);
*p = 'p';
*q = 'q';
I’m a bit shocked, and I have three questions about it.
1- Am I missing something about move semantics and there is a reason for not issuing a warning in this situation, or is gcc’s checking not good enough?
2- Should the next code throw a warning?
char c = 'c';
char *p = &c;
char *q = std::move(p);
*p = 'p';
As far I understand, after std::move(p) p can hold any value, therefore once p is moved is like an uninitialized variable.
3- Can other tools/compilers check these errors?
The code is wrong, so a warning would be good. G++ isn’t smart enough to “see through” the call to
std::move. It’s valid to pass an uninitialized variable by reference to a function (that function might initialize the variable) so callingstd::moveitself doesn’t trigger a warning. Becauseqgets assigned a value, it appears to be initialized to the compiler.If I turn on optimization so that G++ inlines the call to
std::movethen I get an error from G++ 4.7:This is because the call to
std::moveis no longer “opaque” to the compiler, when it analyses the inlined code it can see thatpnever gets assigned a value. The compiler still isn’t smart enough to see thatqnever gets a good value, the cast insidestd::moveprobably confuses the compiler.No.
std::movedoesn’t alter fundamental types such as pointers, so the value ofpwill not be changed. The standard library says that objects are left in a “valid but unspecified” state after being moved from, because the standard doesn’t generally define the exact behaviour of a move constructor or move assignment operator, but for fundamental types such asintandchar*there is no move constructor.std::move(p)just casts the object to an rvalue, it doesn’t alter it, and initializingqwith the value doesn’t alter it either – it just copies the value.Clang and ICC fail to warn about the first example even with optimization on.
Note that although warnings are very useful, compilers are not perfect and it is impossible to warn about all unsafe code. You should not be totally surprised when unsafe code doesn’t get a warning (maybe open a bug report for the compiler to request it be improved) — it doesn’t mean the code is OK. Absence of warnings does not imply absence of bugs.