Main Content

AUTOSAR C++14 Rule A15-3-4

Catch-all (ellipsis and std::exception) handlers shall be used only in (a) main, (b) task main functions, (c) in functions that are supposed to isolate independent components and (d) when calling third-party code that uses exceptions not according to AUTOSAR C++14 guidelines

Since R2020b

Description

Rule Definition

Catch-all (ellipsis and std::exception) handlers shall be used only in (a) main, (b) task main functions, (c) in functions that are supposed to isolate independent components and (d) when calling third-party code that uses exceptions not according to AUTOSAR C++14 guidelines.

Rationale

Catch-all handlers such as catch(std::exception) or catch(...) blocks match many different types of exceptions. If you handle an exception by using such a catch-all handler, you do not have detailed and specific information about the raised exception. Such catch-all handlers cannot take meaningful actions to handle the raised exceptions. These catch-all handlers are useful in processing unexpected exceptions by raising the exceptions again or by properly exiting from the application.

Because catch-all handlers are useful for specific purposes, it is inefficient to use them in every function. Use catch-all handlers in:

  • Main functions

  • Task main functions

  • Functions that call a third-party function that might be noncompliant with AUTOSAR C++14 guidelines

  • Functions that are designed to isolate independent components of your code

Polyspace Implementation

Polyspace® flags catch(std::exception) and catch(...) blocks in a function if none of these are true:

  • The function is the main() function.

  • The function is a task main function.

  • The function calls an external or third-party function that might exit with an exception.

Polyspace detects the main() function. To specify a function as a task main function, use these compilation options:

  • -entry-points <name>

  • -cyclic-tasks <name>

  • -interrupts <name>

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

This example shows how Polyspace flags catch-all handlers in a task main function EntryPoint and a nonentry-point function NonEntryPoint(). To specify the function EntryPoint as a task main function, use the compile option -entry-points EntryPoint.

#include <stdexcept>
#define MYEXCEPTION std::exception &
class ExceptionBased: std::exception {
};
typedef std::exception MyException;
typedef std::exception & MyExceptionRef;

void NonEntryPoint() 
{
	try {
		int i = 2;

		// ...
	} catch (int i) {                   // Compliant
	} catch (int &i) {                  // Compliant
	} catch (std::runtime_error e) {    // Compliant
	} catch (std::runtime_error& e) {   // Compliant
	} catch (std::exception *e) {       // Compliant
	} catch (std::exception e) {        // Noncompliant
	} catch (const std::exception& e) { // Noncompliant
	} catch(MyException e){             // Noncompliant
	} catch(ExceptionBased e){          // Compliant
	} catch (...) {                     // Noncompliant
	}
}
void EntryPoint() noexcept
{
	try {
		int i = 2;

		// ...
	} catch (MyException &e) {          // Compliant
	} catch (MyException e) {           // Compliant
	} catch (MyExceptionRef e) {        // Compliant
	} catch (ExceptionBased e) {        // Compliant
	} catch (const std::exception& e) { // Compliant
	} catch (MYEXCEPTION e) {           // Compliant
	}
}

The function NonEntryPoint() is not a main() or task main function. In this function, Polyspace flags these catch-all blocks:

  • The catch (std::exception e) block matches the different types of exceptions that derive from the class std::exception. This catch-all handler is useful in a main or task main function. Because NonEntryPoint() is neither a main() nor a task main function, Polyspace flags the statement catch (std::exception e). For the same reason, Polyspace flags the statement catch (std::exception& e).

  • MyException is a typedef of std::exception. The catch(MyException e) block matches the different types of exceptions that derive from the class std::except. Because NonEntryPoint() is neither a main nor a task main function, Polyspace flags the statement catch(MyException e).

  • Because NonEntryPoint() is neither a main nor a task main function, Polyspace flags the statement catch(...)

The function EntryPoint() is specified as a task main function. Polyspace does not flag the catch-all blocks in this function.

#include <stdexcept>
void Fextern_throw(void);
void Fextern_nothrow(void) noexcept(true);
void Foo0()
{
	try {
		Fextern_nothrow();
	} catch (...) {                 // Noncompliant
	}
}
void Foo1()
{
	try {
		try {
			Fextern_throw();
		} catch (...) {               // Compliant
		}
	} catch (std::exception& e) {   // Compliant
	}
}
void Foo2()
{
	try {
		try {
			Fextern_nothrow();
		} catch (...) {               // Noncompliant
			Fextern_throw();            
		}
	} catch (std::exception& e) {   // Compliant
	}
}
  • The function Foo0() calls the third-party function Fextern_nothrow(), which is specified as noexcept(true). Because the third-party code is specified as noexcept, Polyspace flags the catch(...) block in Foo0().

  • The function Foo1() calls the third-party function Fextern_throw() that might raise an exception. Because the third-party code might raise an exception, Polyspace does not flag the catch-all handler blocks in Foo1().

  • The function Foo2() contains a nested try-catch block. In the inner block, the external function Fextern_nothrow() is called, which is specified as noexcept(true). Polyspace flags the catch(...) block in the inner try-catch block. The catch-all block in the outer try-catch is compliant because this block handles the exceptions that might be raised by the external function Fextern_throw().

Check Information

Group: Exception handling
Category: Required, Non-automated

Version History

Introduced in R2020b