This is a draft version of a MISRA C++ 202x rule proposed for public review.
MISRA Rule 18.5.1
Category: Advisory
Analysis Type: Undecidable,System
Amplification
A noexcept
function attempts to propagate an exception when it directly or indirectly throws an exception that is not caught within
the function. Any exception that would escape the function causes the program to terminate.
This rule also applies to all functions that are implicitly noexcept
.
If a function’s exception-specifier is of the form noexcept( condition )
, then the function is only permitted to throw an
exception when the condition is false
.
A function’s compliance with this rule is independent of the context in which it is called.
Rationale
Marking a function noexcept
or noexcept( true )
does not prevent an exception from being raised in the body of the
function. However, if the function attempts to propagate an exception to a calling function, the program will be terminated through a call to
std::terminate
. This results in implementation-defined behaviour, including whether or not the stack is unwound before the
program terminates (which may result in dangling resources).
Example
void mayThrow( int32_t x )
{
if ( x < 0 )
{
throw std::exception {};
}
}
void notThrowing()
{
}
void f1( int32_t x ) noexcept // Compliant
{
notThrowing();
}
void f2( int32_t x ) noexcept // Compliant
{
if ( x > 0 ) // This guard ...
{
mayThrow( x ); // ... ensures the call to mayThrow cannot throw
}
}
void f3( int32_t x ) noexcept // Non-compliant - even if f3 is only called in
{ // contexts where x > 0
mayThrow( x );
}
void f4( int32_t x ) noexcept // Compliant - any exception will not propagate
{
try
{
mayThrow( x );
}
catch( ... )
{
}
}
void f5( int32_t x ) noexcept // Non-compliant - exception is rethrown
{
try
{
mayThrow( x );
}
catch ( ... )
{
throw;
}
}
Instantiations of the following template are compliant as they will only be noexcept( true )
when the addition is non-throwing:
template < class T > // Compliant
T plus( T a, T b ) noexcept( noexcept( a + b ) )
{
return a + b;
}
class A
{
~A()
{
throw std::exception {}; // Non-compliant - destructor is implicitly noexcept
}
};
void f6( int32_t x ) throw() // throw() makes function noexcept
{
throw std::exception {}; // Non-compliant
}
Copyright The MISRA Consortium Limited © 2023