MISRA Discussion Forums

Full Version: Misleading statements in Rule 15–1–3.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi all,

In the Rationale for Rule 15–1–3, we have:
Quote:However, syntactically, there is nothing to prevent throw; being used outside a catch handler, where there is no exception object to re-throw. This may lead to an implementation-defined program termination.
There are a couple of problems with this.

First, it't not quite right to refer to a *place* where an exception object can be re-thrown so much as it is to refer to a *time* when such an object can be re-thrown. Refer to 15.1 except.throw. For example, this program:

extern "C" int printf( const char*, ... );

struct A
    A() { (void)printf( "::A::A()\n" ); }
    ~A() { (void)printf( "::A::~A()\n" ); }

void rethrow() { throw; }

void f(  ) {
    try {
        throw A();
    catch (A& p) {
        (void)printf( "entering f()'s handler...\n" );
        (void)printf( "exiting f()'s handler without throwing...\n" );

int main (void) {
    try {
    catch( A& p ) {
        (void)printf( "exiting main()'s handler...\n" );
    return 0;

... yields this output:
entering f()'s handler...
exiting main()'s handler...
(This is specified in the Standard; this is not implementation-defined behavior.)

So the text "where there is no exception object to re-throw" should be changed to something like, "where control could pass at a time when there is no exception object to re-throw".

Second, the rationale text ends with, "This may lead to an implementation-defined program termination."

When you squint at the standardese in just the right way, this sentence is true: it *may* lead to implementation-defined behavior, but only if the non-libary part of the program does not set a terminate_handler. But given the normative text in 15.5.1 except.terminate, it would be much better to change this sentence to:
Quote:If an empty throw is used at a time when there is no exception object to re-throw, std::terminate() is implicitly called. (The stack is not unwound before this call.)
The wording will be reviewed