Unreachable code at constructor's closing brace

c++, constructor, unreachable-code, visual-c++, visual-c++-2008

Solution

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]

Problem

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 ```

Original source