to force gcc to emit additional warnings about unhandled exceptions

A

adaslaw

Hi

Is it possible to force gcc (or xlc) compiler to emit compilation
warning or compilation error for such code:

void fooA() throw (MyException)
{
...
throw MyException();
...
}

void fooB() throw()
{
fooB();
}

I would like to be warned that in function fooB:
* there is no appropriate catch block to catch MyException from fooA
.... or ...
* fooB should be declared as: void fooB() throw(MyException)

Any idea to force the compiler to emit such warnings?

Kind regards,
Adam
 
V

Victor Bazarov

Is it possible to force gcc (or xlc) compiler to emit compilation
warning or compilation error for such code:
[..]

This is a compiler-specific question and should be asked in the
newsgroup dedicated to that compiler. Tool invokation is not
on topic here. This is a language newsgroup.

V
 
Y

Yannick Tremblay

Is it possible to force gcc (or xlc) compiler to emit compilation
warning or compilation error for such code:
[..]

This is a compiler-specific question and should be asked in the
newsgroup dedicated to that compiler. Tool invokation is not
on topic here. This is a language newsgroup.

I usually agree with these anti-off-topic warning. However, in this
case, I think the question is interesting in the general case. So
please allow me to rephrase, retitle and generalize :).

Exceptions specification are generally considered as almost useless in
C++ because they do not stop these exception being thrown, simply
cause undefinite behaviour:

void fooA() throw (MyException)
{
...
throw MyException(); // OK
throw SomeOtherException(); // still compile. Darn!
...
}

void fooB() throw()
{
fooB();
// Nothing warns that fooB() can let exceptions escape
}


Is it possible for a compiler to catch spot these error?

Would it make sense?

Or in the generic sense: can we make them useful rather than as
H. Sutter concludes:
http://www.gotw.ca/publications/mill22.htm
- Moral #1: Never write an exception specification.
- Moral #2: Except possibly an empty one, but if I were you I'd avoid
even that.


Yan
 
J

Joe Greer

(e-mail address removed) (Yannick Tremblay) wrote in @irys.nyx.net:
Is it possible for a compiler to catch spot these error?

Would it make sense?

Or in the generic sense: can we make them useful rather than as
H. Sutter concludes:
http://www.gotw.ca/publications/mill22.htm
- Moral #1: Never write an exception specification.
- Moral #2: Except possibly an empty one, but if I were you I'd avoid
even that.

This question has been discussed to death more than a few times already.
In general, you can't break existing code so the point is moot to start
off. Some of the problems are: 1) How do you specify the exceptions
from an interface? 2) Same thing for function pointers. 3) templates?

The second question is should we care? Googling on Java Checked
exceptions indicates that this is a feature that is only useful for
small to toy programs. The bigger the program, the less return on
investment you get by deploying checked exceptions. In fact,
programmers quickly start just throwing Exception so they don't have to
list the dozen possible exceptions they may see that they don't really
care about because they aren't going to handle them anyway. The other
problem is versioning and maintenance. If a new exception is added to
support a new feature, potentially dozens of classes (which don't care
about this exception) will have to be changed to now accept it as one of
their pass-thrus.

No, I would say that checked exceptions were an experiment that failed.
You will notice that no other languages have been clamouring to add
them.

joe
 
J

Jerry Coffin

[ ... ]
Exceptions specification are generally considered as almost useless in
C++ because they do not stop these exception being thrown, simply
cause undefinite behaviour:

Actually, the behavior is well defined -- it's just behavior that almost
nobody ever really wants.

[ ... ]
Is it possible for a compiler to catch spot these error?

Yes, it's clearly possible in this case. In other cases, it becomes much
more difficult, and in some cases probably impossible. Templates, will
typically have the possibility of throwing exceptions that depend upon
the type(s) over which they're instantiated rather than the code in the
template itself.
Would it make sense?

I don't think so. In fact, I think the whole idea of exception
specifications is fundamentally wrong. They require the author to do a
job to which a compiler is well suited, but a person (as a rule) is
rather poorly suited at best -- specifically, for each function tracking
the union of all exceptions that can be thrown by any lower level code,
and assuring that these are annotated correctly in the exception
specification.

What we really want is NOT an assurance that all intermediate layers of
code are aware of the exceptions that may "bubble up" from below --
rather, we really want an assurance that every exception that can
possibly be thrown is handled appropriately. The compiler lacks the
global view to do the job correctly, so if it's going to be done right,
it has to be done at the linking stage (or some analog thereof) when the
entire program becomes visible.

From there it's a matter of tedious (but rather simple) book-keeping to
track what exceptions can be thrown by what functions, and assuring that
a handler for those exceptions will be in force when each function is
called. That's certainly not easy (by any means) but at least if it's
done that way, you stand a chance of doing more good than harm. If you
insist on polluting the code with exception specifications, I think the
overall effect is inevitably negative rather than positive (and the
larger the program gets, the more strongly negative the result).
 
J

James Kanze

[ ... ]
Exceptions specification are generally considered as almost
useless in C++ because they do not stop these exception
being thrown, simply cause undefinite behaviour:
Actually, the behavior is well defined -- it's just behavior
that almost nobody ever really wants.

What? It's basically the same behavior as an assertion failure.
The exception specification is part of the function's contract,
and if it is violated, you want an assertion failure.

The problem is somewhat more general: with regards to the
contract, there are two things which are generally important to
the client code:

-- it's impossible to write exception safe code without the
guarantee that certain functions (destructors, for example,
or swap if you're using the swap idiom for assignment) will
not generate an exception, so the contract expressed in an
empty exception specifier is very important, and

-- it's important to know that the specific condition X results
in the exception Y being thrown---something, of course, in
which exception specifiers are of no help.

In the end, I think the bad press concerning exception
specifiers is largely based on a misperception of what they
guarantee. What they guarantee is strictly negative: they
guarantee that certain things won't happen. And in practice,
the client is interested either in ) what will happen, when, or
simply in knowing that nothing will happen, that it doesn't have
to worry about recovering from an exception when he calls this
function. (There may be special cases where the client is
interested in only having one specific type of exception, and
nothing else, but they are exceedingly rare.)
 
D

dave_mikesell

The other
problem is versioning and maintenance. If a new exception is added to
support a new feature, potentially dozens of classes (which don't care
about this exception) will have to be changed to now accept it as one of
their pass-thrus.

I've run into this problem at a client, where a shared API uses a Java
API that added an exception in version 1.4.2. In order to upgrade a
project to JDK 1.5, we have to manage this at build time by compiling
the version-specific function that handles the exception. Projects
using the older version still are being supported.
 
J

Jerry Coffin

On Mar 12, 6:33 am, Jerry Coffin <[email protected]> wrote:

[ ... ]
What? It's basically the same behavior as an assertion failure.
The exception specification is part of the function's contract,
and if it is violated, you want an assertion failure.

I find this post rather confusing. You start by seeming to say that I
was dead wrong from beginning to end...

(There may be special cases where the client is
interested in only having one specific type of exception, and
nothing else, but they are exceedingly rare.)

....but then you finish by seeming to agree with what I said -- that
situations that make an exception specification useful are exceedingly
rare.

In the end, I guess I'm not all that worried about whether we agree or
not, but I'm left wondering about what you think of the OP's question:
how often do you see code that really benefits from an exception
specification.

I'd note, in particular, that for most situations I've encountered, that
the ONLY exception guarantee that means much is a guarantee that a
particular piece of code will not throw any exception. Unfortunately,
it's absolutely _impossible_ to write an exception specification that
gives such a guarantee -- no matter how you write it, every exception
specification says that the code in question can throw at least one
exception.

As such, the only way I know of to get what you really want is by
inspecting the code, not by writing an exception specification.
 
Y

Yannick Tremblay

In the end, I guess I'm not all that worried about whether we agree or
not, but I'm left wondering about what you think of the OP's question:
how often do you see code that really benefits from an exception
specification.

Actually, to continue or add precision to my question:

1- I suggest that as they stand in the language, exception
specification are as good as useless (except maybe throw()).

a) Am I wrong, are they useful?

b) Should/could they be removed from the language
(they catch newbies unaware hence are bad)
(or maybe they are good cause they make the language harder hence the
pay rate better?)

c) should/could they be fixed


2- throw(), the non throwing specification

The only execption specification I have ever used is (no)throw(). Even
there, I am in two mind about its value. I have used it for functions
that must be called by exception unaware code, sometimes by pure C
code. However, these functions tend to be written in the style:

ErrorCodeType foo() throw();

ErrorCodeType foo() throw()
{
try
{
// Do some C++
return SuccessValue;
}
catch(...)
{

}
return ErrorValue
}

I guess the compiler will then wrap the whole thing as:

ErrorCodeType compiler_foo()
{
try
{
return foo()
}
catch(...)
{
std::unexpected();
}
}

Assuming the functions themselves are properly written with a top
level try/catch, the non-throw specification become almost useless
however, I can see two small values to it:

1- It call unexpected() if a function is badly written
(unfortunately, at runtime, in a rare failure scenario, probably after
the code has been released, I'd much prefer compile time warning :-( )

2- It documents the interface
("// This function will not throw" could do an almost as good a job)

Both of these are rather weak justification to use it. Almost
insufficient and certainly arguable.

Comments?


Yan
 
J

James Kanze

[ ... ]
What? It's basically the same behavior as an assertion failure.
The exception specification is part of the function's contract,
and if it is violated, you want an assertion failure.
I find this post rather confusing. You start by seeming to say that I
was dead wrong from beginning to end...
...but then you finish by seeming to agree with what I said -- that
situations that make an exception specification useful are exceedingly
rare.

That's what happens when I try to respond to a complex question
in a limited amount of time. Basically, my initial reaction
("What?") was to your statement: "it's just behavior that almost
nobody ever really wants." IMHO, it's actually the most
desirable behavior, most of the time, because:

First, I think everyone would have to agree that exceptions
do form part of the contract of a function, at least in a number
of cases. When they don't, then exception specifications are
irrelevent. Furthermore, I'm fairly convinced that there are
two important cases where they play a role in the contract.

The first is the case when you are guaranteed an exception in
case of a specific error. Most of the time, this sort of error
reporting is better handled by return codes---if it's useful for
the contract to guarantee a certain type of error in certain
conditions, it's almost certainly because it's something the
immediate caller might want to know. There are exceptions,
however---constructors are the most obvious example. In
practice, exception specifications aren't very useful here,
since they actually specify what won't be thrown, and not what
will be thrown (and of course, even if they specified what will
be thrown, they wouldn't specify under which conditions it would
be thrown).

The second case is when the contract guarantees an absense of
exceptions. This can be very important in low level code: you
can't use the swap idiom to implement transactional semantics in
an assignment operator unless the swap function guarantees that
it will not throw. And this is precisely what C++ exception
specifications can provide: a guarantee that no matter what
happens, the function will not throw anything that is not
specified in the exception specifier. Off hand, I can't think
of a case where anything but an empty exception specifier (the
no throw guarantee) would be useful, but I suppose it could
happen: the caller is able to handle one specific type of error,
and catches that exception, but no other exception is possible.
At any, throw() is definitly a useful part of a contract, and if
the contract is violated, you want an assertion failure. And
the specified default behavior of throw() is very much like an
assert---violate the contract, and the program is terminated,
with prejudice.

Given that the only relevant use of exception specifiers *is*
guaranteeing an absense of exceptions (or maybe in some very
special cases, and absense of all but one type of exception),
I'd argue that the specified behavior of them is exactly what is
most often wanted.
In the end, I guess I'm not all that worried about whether we
agree or not, but I'm left wondering about what you think of
the OP's question: how often do you see code that really
benefits from an exception specification.

Any time you need the no throw guarantee. Destructors, swap
functions, etc. Possibly some higher level functions in a
transaction management system (the second phase of a two phase
commit?).

Regretfully, because too many people have mainly considered the
idea of applying them to my first case above, and rejected them
as useless (and they pretty much are, for that case), many
compiler implementors haven't bothered about the quality of
their implementation. (It's interesting to note that Java's
exception specifications seem mainly designed to address the
first case. With very mitigated success, IMHO.)
I'd note, in particular, that for most situations I've
encountered, that the ONLY exception guarantee that means much
is a guarantee that a particular piece of code will not throw
any exception. Unfortunately, it's absolutely _impossible_ to
write an exception specification that gives such a guarantee
-- no matter how you write it, every exception specification
says that the code in question can throw at least one
exception.

No. "throw()" guarantees absolutely that the function will
never exit via an exception. §15.4/8,9:

Whenever an exception is thrown and the search for a
handler (15.3) encounters the outermost block of a
function with an exception-specification, the function
std::unexpected() is called (15.5.2) if the
exception-specification does not allow the exception.

The function std::unexpected() may throw an exception
that will satisfy the exception-specification for which
it was invoked, and in this case the search for another
handler will continue at the call of the function with
this exception specification (see 15.5.2), or it may call
std::terminate().

and in §15.5.2/2:

The std::unexpected() function shall not return, but it
can throw (or re-throw) an exception. If it throws a new
exception which is allowed by the exception
specification which previously was violated, then the
search for another handler will continue at the call of
the function whose exception specification was violated.
If it throws or rethrows an exception that the
exception-specification does not allow then the
following happens: If the exception-specification does
not include the class std::bad_exception (18.7.2.1) then
the function std::terminate() is called, otherwise the
thrown exception is replaced by an
implementation-defined object of the type
std::bad_exception and the search for another handler
will continue at the call of the function whose
exception-specification was violated.

Thus, an exception-specification guarantees that only
the listed exceptions will be thrown. If the
exception-specification includes the type
std::bad_exception then any exception not on the list
may be replaced by std::bad_exception within the
function std::unexpected().

Note that the only thing unexpected is allowed to do is
terminate the program OR throw an exception which is listed in
the exception specifier. If no exception is listed in the
exception specifier, then all it can do is terminate.

Of course, there's no way to guarantee a function will return
normally. It can always call abort(), or exit(). Or someone
can turn the machine off, or do a "kill -9" on your process.
(Which are important considerations to keep in mind when
transactional itegrity is important, but have no effect on the
internal consistency of the program.)
 
J

James Kanze

Actually, to continue or add precision to my question:
1- I suggest that as they stand in the language, exception
specification are as good as useless (except maybe throw()).
a) Am I wrong, are they useful?

Except in very exceptional cases (I've never seen one), the only
useful exception specification is throw(). It is, however, very
useful.
b) Should/could they be removed from the language (they catch
newbies unaware hence are bad) (or maybe they are good cause
they make the language harder hence the pay rate better?)

Well, the no throw guarantee is very useful, and definitely
should not be removed. Practically speaking, I don't think that
it's possible to remove the more general use either. And
although I could imagine a compiler warning about a non empty
exception specification, I'm not really too much in favor of
compiler warnings just because the programmer might not have
understood the language.
c) should/could they be fixed

The no throw guarantee works fine as is, and doesn't need
fixing. Anything else is so rarely used, it doesn't matter.
2- throw(), the non throwing specification
The only execption specification I have ever used is
(no)throw(). Even there, I am in two mind about its value. I
have used it for functions that must be called by exception
unaware code, sometimes by pure C code. However, these
functions tend to be written in the style:
ErrorCodeType foo() throw();
ErrorCodeType foo() throw()
{
try
{
// Do some C++
return SuccessValue;
}
catch(...)
{

}
return ErrorValue
}
I guess the compiler will then wrap the whole thing as:
ErrorCodeType compiler_foo()
{
try
{
return foo()
}
catch(...)
{
std::unexpected();
}
}

The most frequent case of no throw that I see is for C++
functions which intentionally do nothing which can throw.
Things like swap() member functions, constructors of exception
types, etc.
Assuming the functions themselves are properly written with a
top level try/catch, the non-throw specification become almost
useless however, I can see two small values to it:
1- It call unexpected() if a function is badly written
(unfortunately, at runtime, in a rare failure scenario, probably after
the code has been released, I'd much prefer compile time warning :-( )
2- It documents the interface
("// This function will not throw" could do an almost as good a job)
Both of these are rather weak justification to use it. Almost
insufficient and certainly arguable.

In what way are they different from assert()? And assert() is
one of the most important and useful tools I know.
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...

[ ... ]
No. "throw()" guarantees absolutely that the function will
never exit via an exception. §15.4/8,9:

I'm not sure what I was thinking when I said otherwise, but you're
obviously correct.
 
J

Jerry Coffin

[ ... ]
1- I suggest that as they stand in the language, exception
specification are as good as useless (except maybe throw()).

a) Am I wrong, are they useful?

Maybe, but if so only _extremely_ rarely -- I'm pretty sure I've never
seen a useful instance of a nonempty exception specification.
b) Should/could they be removed from the language
(they catch newbies unaware hence are bad)
(or maybe they are good cause they make the language harder hence the
pay rate better?)

They don't really make anything harder, and breaking any code that uses
them is probably unacceptable, even if almost nobody has ever really
suggested that it's a good idea to write such code.
c) should/could they be fixed

They could at least be improved. For example, all nonempty exception
specifications could be deprecated and eventually removed from the
language (i.e. made ill-formed).

I'm not sure that qualifies as "fixed" though -- it has problems for
things like templates that often of the nature "only throws if some set
of operations in the underlying type throws". Concepts (new feature in
C++ 0x) allow you to specify things about the type over which a template
will be instantiated, so you could use this to specify that operations
X, Y and Z of type T cannot throw -- but I don't think there's a way to
say if type T can throw X, Y or Z, then this template can do the same.
2- throw(), the non throwing specification

The only execption specification I have ever used is (no)throw(). Even
there, I am in two mind about its value. I have used it for functions
that must be called by exception unaware code, sometimes by pure C
code.

As James Kanze mentioned elsethread, to produce exception safe code, you
just about need to have a few things you're certain will NOT throw any
exceptions. Destructors, which can be invoked in the process of handling
an exception, are one example. One widely-used method of implementing
assignment depends on swap() never throwing either.

These are generally a few low-level building blocks, however. Most other
code rarely has to worry about the specific exceptions that may be
thrown elsewhere though. Instead, it should be written primarily to
assure that it reacts appropriately when/if any exception is thrown in
lower-level code. In a typical case, that means using RAII, for one
example.
 
J

James Kanze

(e-mail address removed)>, (e-mail address removed)
says...
[ ... ]
No. "throw()" guarantees absolutely that the function will
never exit via an exception. §15.4/8,9:
I'm not sure what I was thinking when I said otherwise, but you're
obviously correct.

An earlier draft of the standard? I too seem to recall having
seen something similar---that regardless of the exception
specification, std::bad_exception could propagate. I wasn't the
only one, however, who found it totally unacceptable, and it
didn't make it into the final version of the standard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top