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
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
foo();
}
~A() {
}
};
int main() {
A a;
}
noreturn_destructor.cpp
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
}
~A() {
foo();
}
};
int main() {
A a;
}
diff -u *.disasm
--- noreturn_constructor.disasm 2012-05-30 11:15:02.000000000 -0400
+++ noreturn_destructor.disasm 2012-05-30 11:15:08.000000000 -0400
@@ -2,7 +2,7 @@
Copyright (C) Microsoft Corporation. All rights reserved.
-Dump of file noreturn_constructor.obj
+Dump of file noreturn_destructor.obj
File Type: COFF OBJECT
@@ -35,15 +35,15 @@
??0A@@QEAA@XZ (public: __cdecl A::A(void)):
0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
- 0000000000000005: 48 83 EC 28 sub rsp,28h
- 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ
- 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h]
- 0000000000000013: 48 83 C4 28 add rsp,28h
- 0000000000000017: C3 ret
+ 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8]
+ 000000000000000A: C3 ret
??1A@@QEAA@XZ (public: __cdecl A::~A(void)):
0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
- 0000000000000005: C3 ret
+ 0000000000000005: 48 83 EC 28 sub rsp,28h
+ 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ
+ 000000000000000E: 48 83 C4 28 add rsp,28h
+ 0000000000000012: C3 ret
Summary
The unreachable code is this implicit return statement, which is generated in the constructor but not the destructor:
- 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h]
+ 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8]
There are no destructors to be called at the end of A::A()
, so that's not the problem. What cannot be reached is the actual construction of the object, which happens after the constructor has finished its execution. Since it can never finish, that compiler-generated code is unreachable.
The declspec(noreturn) on foo is producing this warning. You're telling the compiler that this function does not return. So the compiler is emitting a warning that your constructor will never complete.
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