Reputation: 3101
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
Upvotes: 7
Views: 2112
Reputation: 3101
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]
Upvotes: 3
Reputation: 11028
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.
Upvotes: 2
Reputation: 57
see http://msdn.microsoft.com/en-us/library/k6ktzx3s(v=vs.80).aspx
"This __declspec attribute tells the compiler that a function does not return. As a consequence, the compiler knows that the code following a call to a __declspec(noreturn) function is unreachable."
The closing brace may generate code (like calling destructors), which will not be reached.
Upvotes: 1
Reputation: 4770
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.
Upvotes: 1