I have the following function (reduced example):
QByteArray DecompressBytes(const QByteArray& content){
/* function body (with other return expressions) */
do { return content; } while(content.size() != 0);
}
Last line was added for testing, replacing a macro used. Visual Studio doesn't see a problem with this code, but g++ generates
warning: control reaches end of non-void function [-Wreturn-type]
Changing last line to return content;
removes the warning.
My question: why the compiler behaves this way and what should be the form of the code to avoid any warnings?
The last line used to be ASSERT_FAIL("must be unreachable", content)
with ASSERT_FAIL
expanding into do { ... } while(false)
pattern with another macro replacing while
to forbid non-bool expressions, so the resulting expression was like do { qt_assert_x("", "", 42); return content; } while(::helper::bool_verify(false));
.
g++ version 5.3.0, used with MinGW (standard Qt setup).
Upd: after trying to comment different parts of code (since pure example above doesn't allow to reproduce the problem), something really strange emerged:
QByteArray DecompressBytes(const QByteArray& content){
QByteArray decompressed; //no 'unused variable' warning
do { return content; } while(content.size() != 0);
} //produces warning above
QByteArray DecompressBytes2(const QByteArray& content){
//QByteArray decompressed;
do { return content; } while(content.size() != 0);
} //doesn't produce warning
std::vector<char> DecompressBytes3(const std::vector<char>& content){
std::vector<char> decompressed; //no 'unused variable' warning
do { return content; } while(content.size() != 0);
} //does produce warning
std::vector<char> DecompressBytes4(const std::vector<char>& content){
int decompressed; //unused variable warning is given
do { return content; } while(content.size() != 0);
} //doesn't produce warning
Not sure what all of this means.
That's strange. GCC 4.9.2 with Wall flag doesn't complain about this similar code (I haven't qt installed)
#include <vector>
std::vector<int> foo(const std::vector<int>& v)
{
do { return v; } while( v.size() != 0 );
}
int main() {std::vector<int> v; foo(v);}
Same with clang 4.2.1. As a result I would say that this is something specific to your installation, and if I were you I would add a dummy return statement at the end of the function, or use a flag to get rid of this warning.
Update: Reproduced the behavior of the last two new functions provided by the OP with GCC, while clang raised an 'unused variable' only for DecompressBytes4()
.
One possible explanation is that this do-while you have there is not really used in practice. Dead-code elimination occurs, leaving only the return statement there.
However, when we use an extra variable the dead code elimination mechanism doesn't work in the same way, some information is preserved and it fails to see the return statement.
Usually dead code elimination happens on the back-end, while warnings are raised by the front-end. In this case it seems that these two do not communicate brilliantly! =)
PS - Dead code elimination explains why you don't get an unreachable warning too.