This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Inclusion in an official release of a new throw-like qualifier


I perceived that many people think that the throw qualifiers, as
described by the standard, are not useful, as an example, I quote the
Boost Exception-specification rationale:

Although initially appealing, an exception-specification tends to have
consequences that require very careful thought to understand. The
biggest problem with exception-specifications is that programmers use
them as though they have the effect the programmer would like, instead
of the effect they actually have.
(thanks to Scott McMurray for this quote)

Then, what is the best way to have a reliable description of the
exceptions a method can throw? (Reliable in the sense that this
description can be checked by the compiler).
  Static checks for the existing qualifier are not practical, since
legacy code not using the qualifier in the new way will not compile.
That is what I meant when I said:
 >   theInlineMethod (void) throw () { throw theException(); };
 > this will not even compile...
Jason Merrill wrote:
I doubt that anything like this appears in the standard headers.

(Of course, the method I have write is a toy example). Note that, in this case, the legacy code needs to be _modified_, and cannot be wrapped. Since it is quite impractical, I think that it is necessary to distinguish the qualifier meaning "Not other exceptions than a, b and c can be catched" (i.e., the qualifier as described by the standard) from the qualifier meaning "This method throws no other exceptions than a, b, c". In order to distinguish both qualifiers, a new qualifier can be added. Another option to allow such a distinction is to use the word "static" before the throw qualifier. Of course, the new qualifier (or the word static) will not be used in legacy code. For programs using legacy code, the methods belonging to the legacy code must be wrapped into try/catch blocks (we cannot ensure what the exceptions thrown by such methods are, since the throw qualifier is used in the way described by the standard).
Furthermore, gcc internals currently don't support much in the way of
inter-procedural analysis, and none between routines in separate
modules.
It is not inter-procedural analysis: you only need the prototypes...
If you have a prototype
  void method() _throw foo;
and after that prototype you have a method
  void wrongMethod() _throw () { instance.method(); };
This method can be signaled as incorrect, since method() may throw a
foo exception.
However,
   void rightMethod() _throw () { try {instance.method();} catch(foo)
{ return; } };
can be signaled as correct, since it is known that the only exception
that can be thrown by method() is foo. During the compilation of
method(), it is checked that every throw instruction throws only foo
exceptions (and that every method invoked --as described by the
prototypes-- throws only foo exceptions), or that the other exceptions
are enclosed into corresponding try/catch blocks.
  Hence, note that the analysis can be performed using the code of
the method and the previous prototypes.
I'm strongly opposed to adding a new qualifier with slightly different
semantics from one already in the language.
  I agree that this may cause some confusion. What about the "static
throw" qualifier? In addition, in order to ensure that the code with
the extension will compile in other compilers, a macro STATIC_THROW
can be defined, which expands either to "static throw", if the
extension is supported, or to "throw" if it is not.
  With respect to this,
 > In addition, the semantic meaning is not the same: a
 > throw (a,b,c)  qualifier indicates that you are able only to catch the
 > exceptions a, b and c, and that every other exception will be seen as
 > std::unexpected. Nevertheless, a
 > _throw(a,b,c) qualifier should indicate that the only exceptions that
 > can arise are a, b and c.

But in both cases, the only exceptions that can leave the function are
a, b and c.  I don't see what your extension would add that wouldn't
also be provided by -Wexception-specs.
  Yes, the only exceptions that can leave the function are a, b and
c, but, in addition to the exceptions, you may get a nasty call to
unexpected()... The idea is that if you can write
int main() _throw () { yourCode(); } and your code compile, you will
not have unexpected exceptions thrown during the execution of your
program. Moreover, you have better control of the exceptions that can
be thrown in every point of the execution...
     All the best,
      Sergio


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]