This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Why does debugging "pure virtual method called" have to be so hard?
- To: mark at markmitchell dot com (Mark Mitchell)
- Subject: Re: Why does debugging "pure virtual method called" have to be so hard?
- From: Joe Buck <jbuck at synopsys dot com>
- Date: Tue, 27 Oct 98 9:54:19 PST
- Cc: jbuck at synopsys dot com, oliva at dcc dot unicamp dot br, jason at cygnus dot com, mrs at wrs dot com, egcs at cygnus dot com
> 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.