[llvm-bugs] [Bug 25997] New: [WinEH] no-return function in cleanup code not called with -O

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Jan 2 04:01:47 PST 2016


https://llvm.org/bugs/show_bug.cgi?id=25997

            Bug ID: 25997
           Summary: [WinEH] no-return function in cleanup code not called
                    with -O
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Windows XP
            Status: NEW
          Severity: normal
          Priority: P
         Component: LLVM Codegen
          Assignee: unassignedclangbugs at nondot.org
          Reporter: r.sagitario at gmx.de
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

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 at 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 at 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 at 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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160102/8c490414/attachment.html>


More information about the llvm-bugs mailing list