Bug 10606 - uncaught_exception() returns false too early
Summary: uncaught_exception() returns false too early
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: 4.0.0
Assignee: Richard Henderson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-05-02 21:26 UTC by Martin Sebor
Modified: 2005-02-24 21:19 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.0.0
Last reconfirmed: 2004-08-10 00:55:14


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2003-05-02 16:34:42 UTC
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
Comment 1 Martin Sebor 2003-05-02 21:26:00 UTC
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
Comment 2 Andrew Pinski 2003-05-26 05:03:28 UTC
still happens on the mainline (20030525).
Comment 3 Richard Henderson 2004-02-08 03:49:48 UTC
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~
Comment 4 Jason Merrill 2004-02-09 20:40:39 UTC
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
Comment 5 Paolo Carlini 2004-02-09 21:10:40 UTC
>       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)
Comment 6 Richard Henderson 2004-02-09 21:14:43 UTC
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~
Comment 7 Wolfgang Bangerth 2004-09-13 16:56:44 UTC
Some discussion here: 
  http://gcc.gnu.org/ml/gcc/2004-09/msg00731.html 
Comment 8 Benjamin Kosnik 2004-11-03 00:20:37 UTC
Yo RTH, any word on this?

-benjamin
Comment 9 Martin Sebor 2004-11-03 00:49:33 UTC
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
Comment 10 Giovanni Bajo 2004-11-03 14:47:34 UTC
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.
Comment 11 Giovanni Bajo 2004-11-03 14:48:05 UTC
(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.
Comment 12 Martin Sebor 2004-11-03 16:42:13 UTC
(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).
Comment 13 Richard Henderson 2004-12-03 23:20:31 UTC
I'm not actively working on this, or planning to in the near future.
Comment 14 david.moore 2005-02-18 17:56:18 UTC
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
Comment 15 GCC Commits 2005-02-19 02:35:42 UTC
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

Comment 16 Richard Henderson 2005-02-19 02:38:44 UTC
Fixed.
Comment 17 Paolo Carlini 2005-02-22 11:24:24 UTC
Richard, your fix is causing the regression of libstdc++/14026, can you please
have a look again to both?!? Thanks in advance...
Comment 18 Andrew Pinski 2005-02-22 14:00:45 UTC
(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.
Comment 19 Richard Henderson 2005-02-22 23:19:26 UTC
Fixed.
Comment 20 Benjamin Kosnik 2005-02-24 20:49:50 UTC
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
Comment 21 Richard Henderson 2005-02-24 21:19:28 UTC
You mean different from gcc/testsuite/g++.dg/eh/uncaught1.C?
Comment 22 GCC Commits 2005-04-21 00:28:45 UTC
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