Main Content

AUTOSAR C++14 Rule A15-4-3

The noexcept specification of a function shall either be identical across all translation units, or identical or more restrictive between a virtual member function and an overrider

Since R2020b

Description

Rule Definition

The noexcept specification of a function shall either be identical across all translation units, or identical or more restrictive between a virtual member function and an overrider.

Rationale

Translation units are the different source files that the compiler compiles. When a function has a different exception specification in different source files, it might result in undefined behavior. Similarly, a different exception specification of a polymorphic function in different levels of a class hierarchy might result in compilation failure in some cases. Depending on the software and hardware that you use, different exception specifications of a function in different places might cause a compilation failure or result in undefined behavior leading to security vulnerabilities.

To avoid undefined behavior and security vulnerabilities:

  • Keep the same exception specification in all declarations of a function.

  • If a virtual function is declared by using noexcept or noexcept(true) as the exception specification, declare the overrider functions in the derived classes by using the same specification.

  • If a virtual function is declared by using noexcept(false) as the exception specification, declare the overrider functions in the derived classes by using either noexcept(false) or noexcept(true) as the exception specification.

Polyspace Implementation

Polyspace® flags the exception specification of a function if the function is declared with different exception specifications in different places in a file. Polyspace flags an overrider function in a derived class if it is specified as noexcept(fale) while the virtual function in the base class is specified as noexcept.

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 declarations of one function that has different exception specifications. In one file file1.cpp, the member functions of the classes A and B are declared.

//file1.hpp
class A
{
public:
      void F() noexcept;
      void G() noexcept(false);
	
};
class B
{
public:
      void W() noexcept;
      void R() noexcept(false);
	
};

In another file file2.cpp, the member functions of these classes are defined.

// file2.cpp
#include "file1.hpp"

void A::F() noexcept(false) //Noncompliant
{
	// Implementation
}
void A::G() noexcept //Noncompliant
{
	// Implementation
}


void B::W() noexcept //Compliant
{
	// Implementation
}
void B::R() noexcept(false) //Compliant
{
	// Implementation
}

To see the violations of this rule, run Polyspace and specify both file1.cpp and file2.cpp as source files by using the option -sources. Keep file1.cpp and file2.cpp in the same folder. For more details about specifying multiple source files, see -sources.

The compilation might fail, but Polyspace flags the functions with nonidentical exception specification.

  • The function A::F() is declared infile1.cpp by using the exception specification noexcept, but it is declared by using the exception specification noexcept(false) in file2.cpp. Polyspace flags the nonidentical exception specification in the latter declaration. For the same reason, the exception specification of A::G() in file2.cpp is also flagged.

  • The functions B::W() and B::R() are declared and defined by using the same exception specification in the two source files. These functions are compliant with this rule.

This example shows how Polyspace flags the declaration of overrider functions that have less restrictive exception specifications.

class A
{
public:
	virtual void V1() noexcept = 0;
	virtual void V2() noexcept(false) = 0;
	virtual void V3() noexcept = 0;
};
class B : public A
{
public:
	void V1() noexcept(false) override //Noncompliant
	{
		// Implementation
	}
	void V2() noexcept override //Compliant
	{
		// Implementation
	}
	void V3() noexcept override //Compliant
	{
		// Implementation
	}
};

The pure virtual functions A::V1(), A::V2(), and A::V3() are implemented by the overriding functions B::V1(), B::V2(), and B::V3() respectively.

  • Polyspace flags the function B::V1() because this overriding function is specified by using the less restrictive exception specification noexcept(false) compared to the base class virtual function A::V1(), which is specified by using noexcept.

  • Polyspace does not flag B::V2() because this overriding function is specified by using the more restrictive specification noexcept compared to the base class virtual function A::V2(), which is specified by using noexcept(false).

  • Polyspace does not flag B::V3() because this overriding function is specified by using the same exception specification as the base class virtual function A::V3().

Check Information

Group: Exception handling
Category: Required, Automated

Version History

Introduced in R2020b