I'm working on an application built with VC9 and I've hit upon a warning I don't fully understand: why is there an "unreachable code" warning on the closing brace of the constructor?
The minimal testcase to reproduce the issue is:
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
foo();
} // d:\foo.cpp(7) : warning C4702: unreachable code
};
int main() {
A a;
}
This must be compiled with /W4 to trigger the warning. Alternatively, you can compile with /we4702 to force an error on the detection of this warning.
d:\>cl /c /W4 foo.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
foo.cpp
d:\foo.cpp(7) : warning C4702: unreachable code
Can someone explain what, precisely, is unreachable here? My best theory is that it's the destructor, but I'd like a definitive answer.
If I want to make this code warning-clean, how can I achieve that? The best I can come up with is convert this to a compile-time error.
struct A {
private:
A(); // No, you can't construct this!
};
int main() {
A a;
}
Edit: for clarification, terminating the program with a noreturn function doesn't normally cause an unreachable code warning on the closing brace enclosing that function call.
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
}
~A() {
foo();
}
};
int main() {
A a;
}
Results in:
d:\>cl /c /W4 foo3.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
foo3.cpp
Gorpik is on the right track. I've created two similar test cases, compiled them, and disassembled them and I think I've come to understand the underlying reason: the constructor always generates a return statement implicitly and this return statement is unreachable due to the noreturn function.
noreturn_constructor.cpp
noreturn_destructor.cpp
diff -u *.disasm
The unreachable code is this implicit return statement, which is generated in the constructor but not the destructor: