https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68184

            Bug ID: 68184
           Summary: Exception from a virtual function does not get caught
           Product: gcc
           Version: 5.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: philodej at gmail dot com
  Target Milestone: ---

Hi!
The following code terminates on g++ 5.2.1, 4.9.3 and 4.8.4:

namespace {
struct IFoo { virtual void foo() = 0; };
struct IBar { virtual void bar() = 0; };

struct FooBar : private IBar, private IFoo
{
    void call_foo()
    {
        try
        {
            static_cast<IFoo*>(this)->foo();
        }
        catch( ... ) {}
    }
    void foo() { throw 1; }
    void bar()  {}
};

void test()
{
    FooBar foobar;
    foobar.call_foo();
}
}
int main()
{
    test();
    return 0;
}

when compiled with O3 optimization
  g++ -O3 -Wall -Wextra -pedantic main.cpp && ./a.out
with following error:
  terminate called after throwing an instance of 'int'

For the example see:
  http://coliru.stacked-crooked.com/a/2bab7c03ff7c870b

It seems that __cxa_begin_catch, __cxa_end_catch calls do not get generated:

(anonymous namespace)::FooBar::bar():
        rep ret
(anonymous namespace)::FooBar::foo():
        movl    $4, %edi
        subq    $8, %rsp
        call    __cxa_allocate_exception
        xorl    %edx, %edx
        movl    $1, (%rax)
        movl    typeinfo for int, %esi
        movq    %rax, %rdi
        call    __cxa_throw
non-virtual thunk to (anonymous namespace)::FooBar::foo():
        subq    $8, %rdi
        jmp     .LTHUNK0
main:
        subq    $24, %rsp
        leaq    8(%rsp), %rdi
        movq    vtable for (anonymous namespace)::FooBar+16, (%rsp)
        movq    vtable for (anonymous namespace)::FooBar+48, 8(%rsp)
        call    non-virtual thunk to (anonymous namespace)::FooBar::foo()
        xorl    %eax, %eax
        addq    $24, %rsp
        ret

When I comment-out the IBar::bar() interface method, call the foo() method
without static cast, use an older compiler (<= 4.6.4), or do some other code
experiments then everything works as expected: 

  - terminate:               http://goo.gl/jcgPn6
  - single virtual function: http://goo.gl/cayyoO
  - no static cast:          http://goo.gl/i9N4pD
  - O1 + noinline:           http://goo.gl/PYazij
  - g++ 4.6.4:               http://goo.gl/uWQ6aU

Thanks in advance.

Reply via email to