<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - [WinEH] no-return function in cleanup code not called with -O"
   href="https://llvm.org/bugs/show_bug.cgi?id=25997">25997</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[WinEH] no-return function in cleanup code not called with -O
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows XP
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>r.sagitario@gmx.de
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This code:

#include <stdlib.h>
#include <stdio.h>

struct Cleanup
{
    ~Cleanup()
    {
        puts("abort");
        exit(42);
    }
};

void test()
{
    try
    {
        Cleanup a;
        throw int(3);
    }
    catch(int)
    {
    }
}

int main(int argc, char** argv)
{
    test();
}

compiles and runs correctly (prints "abort" and has exit code 42) when built
with "clang -fexceptions -m32". Adding "-O" to the command line causes the
program to crash.

The C++ code itself seems questionable, but other languages support arbitrary
code in "finally" blocks, e.g. throwing another exception.

The IR for the test function:

define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)*
@__CxxFrameHandler3 to i8*) {
entry:
  %a = alloca %struct.Cleanup, align 1
  %tmp = alloca i32, align 4
  store i32 3, i32* %tmp, align 4
  %0 = bitcast i32* %tmp to i8*
  invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #4
          to label %unreachable unwind label %ehcleanup

ehcleanup:                                        ; preds = %entry
  %1 = cleanuppad within none []
  call x86_thiscallcc void @"\01??1Cleanup@@QAE@XZ"(%struct.Cleanup* %a) #5 [
"funclet"(token %1) ]
  cleanupret from %1 unwind label %catch.dispatch

catch.dispatch:                                   ; preds = %ehcleanup
  %2 = catchswitch within none [label %catch] unwind to caller

catch:                                            ; preds = %catch.dispatch
  %3 = catchpad within %2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8*
null]
  catchret from %3 to label %catchret.dest

catchret.dest:                                    ; preds = %catch
  br label %try.cont

try.cont:                                         ; preds = %catchret.dest
  ret void

unreachable:                                      ; preds = %entry
  unreachable
}

The problem here is that the optimizer infers "noreturn" from the cleanup call
and replaces "cleanupret" with "unreachable":

define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)*
@__CxxFrameHandler3 to i8*) {
entry:
  %a = alloca %struct.Cleanup, align 1
  %tmp = alloca i32, align 4
  %0 = getelementptr inbounds %struct.Cleanup, %struct.Cleanup* %a, i32 0, i32
0
  call void @llvm.lifetime.start(i64 1, i8* %0) #6
  store i32 3, i32* %tmp, align 4, !tbaa !4
  %1 = bitcast i32* %tmp to i8*
  invoke void @_CxxThrowException(i8* %1, %eh.ThrowInfo* nonnull @_TI1H) #7
          to label %unreachable unwind label %ehcleanup

ehcleanup:                                        ; preds = %entry
  %2 = cleanuppad within none []
  call x86_thiscallcc void @"\01??1Cleanup@@QAE@XZ"(%struct.Cleanup* nonnull
%a) #6 [ "funclet"(token %2) ]
  unreachable

unreachable:                                      ; preds = %entry
  unreachable
}

This seems to break the funclet extraction mechanism for the Windows exception
handling.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>