From mboxrd@z Thu Jan 1 00:00:00 1970 From: Joe Buck To: mark@markmitchell.com (Mark Mitchell) Cc: jbuck@synopsys.com, oliva@dcc.unicamp.br, jason@cygnus.com, mrs@wrs.com, egcs@cygnus.com Subject: Re: Why does debugging "pure virtual method called" have to be so hard? Date: Tue, 27 Oct 1998 16:33:00 -0000 Message-id: <199810271754.JAA16953@atrus.synopsys.com> References: <199810271639.IAA16237@smtp.earthlink.net> X-SW-Source: 1998-10/msg01082.html > Joe> I vote for throw __pure_virtual_exception; > Joe> where that class is derived from class std::exception. Sorry I chose that phrase: I meant that I would have voted for something like this in the standard. Mark Mitchell points out: > class C { > virtual void f () throw () = 0; > }; > > C& c = g(); > c.f(); and the fact that the optimizer may wish to use the no-throw guarantee. (The following is just a mental exercise; I'm not asking anyone to do any actual work to implement it. Think of it as food for thought). Let's say that we were on the committee, and the proposal was that pure_virtual_exception were to be thrown and this was your response. It would seem, then, that in this case (the user has specified no exceptions) the attempt to throw pure_virtual_exception would be bad, so std::unexpected() should be called. Since the compiler knows that any call will be turned into a std::unexpected, it can wire the vtbl entry for C::f directly to std::unexpected. So, the change would be as follows: currently the vtbl gets a pointer to __pure_virtual. __pure_virtual would be changed to throw an exception. At this stage, we've made no changes to the compiler itself, just to the support library. If, however, there is a throw specification like the above, __pure_virtual_nothrow would be pointed to instead. Now we've changed the compiler. What if we have something like virtual void f () throw (Foo, Bar) = 0; There are always two possibilities: the specification allows __pure_virtual_exception to pass, or it does not. So the ideal compiler would generate one of the two calls. If we can't tell or we are lazy, it would be better to make mistakes in favor of not throwing (so the optimizer won't make bad code), so a simple thing would be to generate the _nothrow version if there is any throw specification at all. > I think calling terminate, abort, or some such is just fine. Currently __pure_virtual is void __pure_virtual () { #ifndef inhibit_libc write (2, MESSAGE, sizeof (MESSAGE) - 1); #endif _exit (-1); } The _exit(-1) could be easily changed to abort(), and people debugging the problem could still set a breakpoint on __pure_virtual. Maybe that one-line change is the one we should really make.