From: Martin Sebor <sebor@roguewave.com> To: gcc-gnats@gcc.gnu.org Cc: Subject: Re: c++/10606: uncaught_exception() returns false too early Date: Fri, 02 May 2003 16:34:42 -0600 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=10606 Here's another test case that also shows that the function fails to return true after the exception has been rethrown: $ cat t.cpp; g++ t.cpp && ./a.out #include <stdio.h> #include <exception> void foo (const void*); int main () { #define SHOW(fun) \ printf ("%s(%d): %s: uncaught_exception() = %d\n", \ __FILE__, __LINE__, fun, std::uncaught_exception ()) static int n; struct S { int id; S (): id (n++) { printf ("S::S() [%d]: uncaught_exception() = %d\n", id, std::uncaught_exception ()); } S (const S &s): id (n++) { printf ("S::S(const S& [%d]) [%d]: uncaught_exception() = %d\n", s.id, id, std::uncaught_exception ()); } ~S () { printf ("S::~S() [%d]: uncaught_exception() = %d\n", id, std::uncaught_exception ()); } }; try { try { S s; SHOW ("throw"); throw s; } catch (S s) { SHOW ("catch"); foo (&s); throw; } } catch (S s) { SHOW ("catch"); foo (&s); } } void foo (const void*) { } S::S() [0]: uncaught_exception() = 0 t.cpp(32): throw: uncaught_exception() = 0 S::S(const S& [0]) [1]: uncaught_exception() = 0 S::~S() [0]: uncaught_exception() = 1 S::S(const S& [1]) [2]: uncaught_exception() = 0 t.cpp(36): catch: uncaught_exception() = 0 S::~S() [2]: uncaught_exception() = 0 S::S(const S& [1]) [3]: uncaught_exception() = 0 t.cpp(42): catch: uncaught_exception() = 0 S::~S() [3]: uncaught_exception() = 0 S::~S() [1]: uncaught_exception() = 0
The program below shows that the gcc implementation of uncaught_exception() violates 15.5.3, p1. Specifically, the function is required to return true "until completing the initialization of the exception-declaration in the matching handler" which the gcc impletation fails to do (the output line marked <<<). Martin Release: 3.2 How-To-Repeat: $ cat t.cpp; g++ t.cpp && ./a.out #include <stdio.h> #include <exception> int main () { #define SHOW(fun) \ printf ("%s(%d): %s: uncaught_exception() = %d\n", \ __FILE__, __LINE__, fun, std::uncaught_exception ()) struct S { S () { SHOW ("S::S()"); } S (const S &s) { SHOW ("S::S(const S&)"); } ~S () { SHOW ("S::~S()"); } }; try { S s; throw s; } catch (S s) { SHOW ("catch"); } } t.cpp(11): S::S(): uncaught_exception() = 0 t.cpp(12): S::S(const S&): uncaught_exception() = 0 t.cpp(13): S::~S(): uncaught_exception() = 1 t.cpp(12): S::S(const S&): uncaught_exception() = 0 <<< t.cpp(21): catch: uncaught_exception() = 0 t.cpp(13): S::~S(): uncaught_exception() = 0 t.cpp(13): S::~S(): uncaught_exception() = 0
still happens on the mainline (20030525).
Subject: Re: uncaught_exception() returns false too early Jason, is the analysis in this PR correct? If so, I guess the IA-64 EH ABI isn't good enough. We'd need to add a new entry point to be used with catch types with non-trivial constructors. Something like: struct S s; T.1 = __cxa_begin_catch_part1 (<<eh object>>); try { try { __comp_ctor (&s, T.1) } catch { terminate (); } __cxa_begin_catch_part2 (<<eh object>>); try { // handler } finally { __comp_dtor (&s); } } finally { __cxa_end_catch (); } r~
Subject: Re: uncaught_exception() returns false too early On Sat, 7 Feb 2004 19:49:45 -0800, Richard Henderson <rth@redhat.com> wrote: > Jason, is the analysis in this PR correct? Looks like. And we also aren't incrementing uncaught_exception soon enough on a rethrow; we should do it in cxa_rethrow instead of cxa_end_catch. > If so, I guess the IA-64 EH ABI isn't good enough. We'd need to add a > new entry point to be used with catch types with non-trivial > constructors. Makes sense. Jason
> And we also aren't incrementing uncaught_exception soon enough > on a rethrow; we should do it in cxa_rethrow instead of cxa_end_catch. Oh, really?!? If I understand well what you are saying, in my tree I had a trivial tentative fix for 14026 (mentioned on IRC ;) which did exactly that! Then Richard fixed it in the other way (not decreasing the counter in cxa_begin_catch, basically)
Subject: Re: uncaught_exception() returns false too early On Mon, Feb 09, 2004 at 09:10:43PM -0000, pcarlini at suse dot de wrote: > If I understand well what you are saying, in my tree I had a trivial > tentative fix for 14026 (mentioned on IRC ;) which did exactly that! > Then Richard fixed it in the other way (not decreasing the counter > in cxa_begin_catch, basically) I had interpreted that situation differently, since the exception is still caught at a different nesting level. Perhaps I'm wrong. r~
Some discussion here: http://gcc.gnu.org/ml/gcc/2004-09/msg00731.html
Yo RTH, any word on this? -benjamin
FWIW, if you missed it there was a discussion of this issue on c++std-core@accu.org, starting with c++std-core-10643. Mike Miller said he'd open an issue for it. I don't see it on the list yet but I assume it will be in in the post-Redmond mailing. AFAIK, he plans to push for the EDG behavior (but not that of Intel C++). If it's accepted the output of the original test case would be required to be (note that the value is already true in the copy ctor): S::S() [0]: uncaught_exception() = 0 t.cpp(32): throw: uncaught_exception() = 0 S::S(const S& [0]) [1]: uncaught_exception() = 1 S::~S() [0]: uncaught_exception() = 1 S::S(const S& [1]) [2]: uncaught_exception() = 1 t.cpp(36): catch: uncaught_exception() = 0 S::~S() [2]: uncaught_exception() = 1 S::S(const S& [1]) [3]: uncaught_exception() = 1 t.cpp(42): catch: uncaught_exception() = 0 S::~S() [3]: uncaught_exception() = 0 S::~S() [1]: uncaught_exception() = 0
If the issue is still under the C++ committee, this bug should be suspended. Unless there is something which is *surely* wrong with C++ and that can be fixed meanwhile.
(In reply to comment #10) > If the issue is still under the C++ committee, this bug should be suspended. > Unless there is something which is *surely* wrong with C++ and that can be > fixed meanwhile. I meant "wrong with G++" of course.
(In reply to comment #10) I think it's clear that gcc is wrong in not returning true in the initializer of the exception object in the catch handler (the second invocation of the copy ctor in the test case). What's not so clear cut is whether it should also do so during the creation of the temporary exception object (the first invocation of the copy ctor).
I'm not actively working on this, or planning to in the near future.
As the person who has been working on similar problems in the Intel Compiler, Martin and I had some lengthy discussions about this during which he convinced me he was correct. The result was issue 475 in the active C++ core issues list. Its now clear that uncaught_exception should be on during the copy construction of temporary that is thrown. Thinking about the user model, it seems that this is the only model that makes sense. I believe the standard clarifications in this issue will be made but that in any case, the issue is clear enough at this point to proceed. M2CW. David Moore
Subject: Bug 10606 CVSROOT: /cvs/gcc Module name: gcc Changes by: rth@gcc.gnu.org 2005-02-19 02:35:25 Modified files: gcc/cp : ChangeLog except.c libstdc++-v3 : ChangeLog libstdc++-v3/config: linker-map.gnu libstdc++-v3/libsupc++: eh_alloc.cc eh_catch.cc eh_throw.cc unwind-cxx.h Added files: gcc/testsuite/g++.dg/eh: uncaught1.C Log message: PR libstdc++/10606 gcc/cp/ * except.c (do_get_exception_ptr): New. (expand_start_catch_block): Use it. libstdc++/ * config/linker-map.gnu (CXXABI_1.3.1): Add __cxa_get_exception_ptr. * libsupc++/eh_alloc.cc (__cxa_allocate_exception): Increment uncaughtExceptions here instead of ... * libsupc++/eh_throw.cc (__cxa_throw) ... here. (__cxa_rethrow): Increment uncaughtExceptions here instead of ... * libsupc++/eh_catch.cc (__cxa_end_catch): ... here. (__cxa_get_exception_ptr): New. * libsupc++/unwind-cxx.h (__cxa_get_exception_ptr): Declare. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4637&r2=1.4638 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/except.c.diff?cvsroot=gcc&r1=1.180&r2=1.181 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/eh/uncaught1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.2901&r2=1.2902 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/config/linker-map.gnu.diff?cvsroot=gcc&r1=1.77&r2=1.78 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/eh_alloc.cc.diff?cvsroot=gcc&r1=1.11&r2=1.12 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/eh_catch.cc.diff?cvsroot=gcc&r1=1.8&r2=1.9 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/eh_throw.cc.diff?cvsroot=gcc&r1=1.8&r2=1.9 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/libsupc++/unwind-cxx.h.diff?cvsroot=gcc&r1=1.7&r2=1.8
Fixed.
Richard, your fix is causing the regression of libstdc++/14026, can you please have a look again to both?!? Thanks in advance...
(In reply to comment #17) > Richard, your fix is causing the regression of libstdc++/14026, can you please > have a look again to both?!? Thanks in advance... PR 20091 was opened for this regression.
I'd like to add a testcase for this, based on the mailing list commentary here: http://gcc.gnu.org/ml/libstdc++/2005-01/msg00035.html Although I suppse the 475 wording would also be sufficient. Thoughts? I think this is tricky enough that unless something is added to test for this, future changes risk unitentional breakage. -benjamin
You mean different from gcc/testsuite/g++.dg/eh/uncaught1.C?
Subject: Bug 10606 CVSROOT: /cvs/gcc Module name: gcc Branch: apple-local-200502-branch Changes by: dpatel@gcc.gnu.org 2005-04-21 00:28:36 Modified files: gcc/cp : ChangeLog.apple-ppc except.c Log message: Radar 4093536 Undo PR libstdc++/10606 fix. 2005-02-18 Richard Henderson <rth@redhat.com> PR libstdc++/10606 * except.c (do_get_exception_ptr): New. (expand_start_catch_block): Use it. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.apple-ppc.diff?cvsroot=gcc&only_with_tag=apple-local-200502-branch&r1=1.1.4.5&r2=1.1.4.6 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/except.c.diff?cvsroot=gcc&only_with_tag=apple-local-200502-branch&r1=1.180.2.1&r2=1.180.2.2