Bug 68184 - [4.9 Regression] Exception from a virtual function does not get caught
Summary: [4.9 Regression] Exception from a virtual function does not get caught
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.2.1
: P2 normal
Target Milestone: 5.4
Assignee: Jan Hubicka
URL:
Keywords: wrong-code
: 68922 69874 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-11-02 16:08 UTC by Petr Filipsky
Modified: 2016-08-03 10:58 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.3.4, 5.4.0, 6.0
Known to fail: 4.8.5, 5.2.0, 5.3.0
Last reconfirmed: 2015-11-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Petr Filipsky 2015-11-02 16:08:45 UTC
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.
Comment 1 Richard Biener 2015-11-03 10:41:01 UTC
Confirmed.  Works with -O0 and fails with -O1+.  Works with GCC 4.3.
Comment 2 Mikael Pettersson 2015-11-08 17:33:08 UTC
Works with gcc 4.6.4, fails with 4.7.4, 4.8.5, 4.9.3, 5.2.1, and 6.0.0.  The failure started with r173517 -- a chunk of exception handling meta-data and code disappears with that revision.
Comment 3 Richard Biener 2015-11-18 12:17:30 UTC
Honza?
Comment 4 Jan Hubicka 2015-12-01 18:58:40 UTC
Will take a look
Comment 5 Jan Hubicka 2015-12-01 19:11:20 UTC
Will take a look. This is ipa-pure-const bug.  We have:

{anonymous}::FooBar::_ZThn8_N12_GLOBAL__N_16FooBar3fooEv (_3);

(i.e. we now devirtualize to call to thunk) and consequently we mark:

Function found to be nothrow: virtual void {anonymous}::FooBar::_ZThn8_N12_GLOBAL__N_16FooBar3fooEv()

I suppose ipa-pure-const is confused about same body alias wich is used to call the virtual method.
Comment 6 Jan Hubicka 2015-12-03 04:14:05 UTC
Author: hubicka
Date: Thu Dec  3 04:13:33 2015
New Revision: 231217

URL: https://gcc.gnu.org/viewcvs?rev=231217&root=gcc&view=rev
Log:

	PR ipa/68184
	* g++.dg/torture/pr68184.C: New testcase.
	* cgraphunit.c (cgraph_node::analyze): Set can_throw_external.

Added:
    trunk/gcc/testsuite/g++.dg/torture/pr68184.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cgraphunit.c
    trunk/gcc/testsuite/ChangeLog
Comment 7 Jan Hubicka 2015-12-03 04:39:34 UTC
Fixed on trunk so far
Comment 8 Richard Biener 2015-12-16 09:04:12 UTC
*** Bug 68922 has been marked as a duplicate of this bug. ***
Comment 9 Richard Biener 2015-12-16 11:12:37 UTC
Author: rguenth
Date: Wed Dec 16 11:12:06 2015
New Revision: 231677

URL: https://gcc.gnu.org/viewcvs?rev=231677&root=gcc&view=rev
Log:
2015-12-16  Richard Biener  <rguenther@suse.de>

	Backport from mainline
	2015-12-02  Jan Hubicka  <hubicka@ucw.cz>

	PR ipa/68184
	* cgraphunit.c (cgraph_node::analyze): Set can_throw_external.
 
	* g++.dg/torture/pr68184.C: New testcase.

Added:
    branches/gcc-5-branch/gcc/testsuite/g++.dg/torture/pr68184.C
Modified:
    branches/gcc-5-branch/gcc/ChangeLog
    branches/gcc-5-branch/gcc/cgraphunit.c
    branches/gcc-5-branch/gcc/testsuite/ChangeLog
Comment 10 Richard Biener 2015-12-16 11:13:33 UTC
And for GCC 5.4.
Comment 11 Markus Trippelsdorf 2016-03-05 15:26:53 UTC
*** Bug 69874 has been marked as a duplicate of this bug. ***
Comment 12 Richard Biener 2016-08-03 10:58:44 UTC
Fixed in GCC 5.4+