メインコンテンツ

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

説明

ルール定義

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.

根拠

翻訳単位は、コンパイラがコンパイルする別のソース ファイルです。関数に別のソース ファイル内の別の例外指定が含まれている場合は、未定義動作を引き起こす可能性があります。同様に、クラス階層のレベルによって多相型関数の例外指定が異なる場合も、コンパイル エラーにつながる可能性があります。使用しているソフトウェアとハードウェアによっては、場所によって関数の例外指定が異なるために、コンパイル エラーを引き起こしたり、セキュリティの脆弱性につながる未定義動作が発生したりする可能性があります。

未定義動作とセキュリティの脆弱性を回避するには:

  • 関数のすべての宣言で同じ例外指定を維持します。

  • noexcept または noexcept(true) を例外指定として使用してバーチャル関数を宣言した場合は、同じ指定を使用して派生クラスでオーバーライダー関数を宣言します。

  • noexcept(false) を例外指定として使用してバーチャル関数を宣言した場合は、noexcept(false)noexcept(true) のどちらかを例外指定として使用して派生クラスでオーバーライダー関数を宣言します。

Polyspace 実装

Polyspace® は、関数がファイル内の別の場所にある異なる例外指定を使用して宣言された場合にその関数の例外指定にフラグを設定します。基底クラス内のバーチャル関数が noexcept として指定されており、かつ派生クラス内のオーバーライダー関数が noexcept(fale) として指定される場合に、Polyspace はその派生クラス内のオーバーライダー関数にフラグを設定します。

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

この例では、複数の異なる例外指定を含む 1 つの関数の宣言に、Polyspace がどのようにフラグを設定するかを示します。1 つのファイル file1.cpp 内で、クラスの AB のメンバー関数が宣言されます。


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

別のファイル file2.cpp 内で、これらのクラスのメンバー関数が定義されます。


// 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
}

このルールの違反を確認するには、Polyspace を実行し、オプション -sources を使用して file1.cppfile2.cpp の両方をソース ファイルとして指定します。file1.cppfile2.cpp を同じフォルダーに入れます。複数のソース ファイルの指定の詳細については、-sources を参照してください。

コンパイルは失敗する可能性がありますが、Polyspace は異なる例外指定を含む関数にフラグを設定します。

  • 関数 A::F() は、file1.cpp では例外指定 noexcept を使用して宣言されますが、file2.cpp では例外指定 noexcept(false) を使用して宣言されます。Polyspace は、後者の宣言内の異なる例外指定にフラグを設定します。同じ理由で、file2.cpp 内の A::G() の例外指定にもフラグが設定されます。

  • 関数の B::W()B::R() は、2 つのソース ファイル内の同じ例外指定を使用して宣言および定義されます。これらの関数はこのルールに準拠しています。

この例では、より限定的ではない例外指定を含むオーバーライダー関数の宣言に、Polyspace がどのようにフラグを設定するかを示します。


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
	}
};

純粋なバーチャル関数の A::V1()A::V2()、および A::V3() はそれぞれ、オーバーライド関数の B::V1()B::V2()、および B::V3() によって実装されます。

  • Polyspace は関数 B::V1() にフラグを設定します。これは、noexcept を使用して指定される基底クラスのバーチャル関数 A::V1() と比較して、より限定的ではない例外指定 noexcept(false) を使用してこのオーバーライド関数が指定されるためです。

  • Polyspace はB::V2() にフラグを設定しません。これは、noexcept(false) を使用して指定される基底クラスのバーチャル関数 A::V2() と比較して、より限定的な指定 noexcept を使用してこのオーバーライド関数が指定されるためです。

  • Polyspace は B::V3() にフラグを設定しません。これは、このオーバーライド関数が、基底クラスのバーチャル関数 A::V3() と同じ例外指定を使用して指定されるためです。

チェック情報

グループ: Exception handling
カテゴリ: Required、Automated

バージョン履歴

R2020b で導入