メインコンテンツ

MISRA C:2012 Rule 23.7

A generic selection that is expanded from a macro should evaluate its argument only once

R2024a 以降

説明

ルール定義

A generic selection that is expanded from a macro should evaluate its argument only once 1 .

This rule comes from MISRA C™:2012 Amendment 3.

根拠

総称選択の制御引数が評価されないため、関連リストの式が一貫性のない方法で評価されると、予期しない結果が発生する可能性があります。たとえば、マクロ引数を評価することに二次的影響がある場合に、関連リストでその引数が一貫性のない方法で評価されると、選択によってはその二次的影響が生じないことがあります。

総称選択がマクロから展開される場合は、選択されている関連に関係なく、関連リストでマクロ引数が 1 回評価されます。引数を一貫性のある方法で評価するには、総称選択の関連リストの外部で引数を評価します。

Polyspace 実装

Polyspace® は、総称選択がマクロから展開され、関連リストの少なくとも 1 つの式がマクロ引数を評価しない場合に、このルールの違反を報告します。

関連リストのすべての式で引数が評価されない場合、Polyspace は違反を報告しません。例外として、関連リストのすべての式が定数式の場合は、このルールには違反しません。

トラブルシューティング

ルール違反を想定していてもその違反が表示されない場合、コーディング規約違反が想定どおりに表示されない理由の診断を参照します。

すべて展開する

この例では、総称選択がすべての関連のマクロ引数を評価しません。たとえば、マクロ NONCOMPLIANT1char 関連ではマクロ引数が評価されません。Polyspace は次のマクロについて欠陥を報告します。

#include <stdint.h>

void getInt(int);
void getChar(char);
void getDefault(void);

// Macro argument isn't evaluated in case of 'char'
#define NONCOMPLIANT1(X) _Generic((X), int : (X), char : 0 ) /* Noncompliant */ 

// Macro isn't evaluated in case of 'int'
#define NONCOMPLIANT2(X) _Generic((X), int : 1, default : (X)) /* Noncompliant */ 

// Macro argument isn't evaluated in the default case.
#define NONCOMPLIANT3(X) _Generic((X), int : getInt(X), char : getChar(X), default : getDefault )/* Noncompliant */ 

void foo(int i) {
	NONCOMPLIANT1(0);
	NONCOMPLIANT1(i);
	NONCOMPLIANT2(0);
	NONCOMPLIANT3(0);
}

この例では、ルールに準拠している総称選択を示します。

  • マクロ COMPLIANT1 は関連リストでその引数を評価しません。このケースでは Polyspace は違反を報告しません。

  • マクロ COMPLIANT2 は、関連リスト外部でマクロ引数を 1 回評価します。これは MISRA™ で推奨されている使用法です。ルール チェッカーは、このケースについて違反を報告しません。

  • 例外として、マクロ EXCEPTION に示すように、関連リストのすべての式が定数式の場合、ルール チェッカーは違反を報告しません。

#include <stdint.h>

void doInt(void);
void doChar(void);
void doDefault(void);

void getInt(int);
void getChar(char);
void getDefault(void);

// Macro argument is never evaluated in the _Generic cases.
#define COMPLIANT1(X) _Generic((X), int : doInt, char : doChar, default: doDefault ) /* Compliant */ 

// Recommended standard usage.
#define COMPLIANT2(X) _Generic((X), int : getInt, char: getChar) (X) /* Compliant */ 

#define EXCEPTION(P) _Generic((P), int const* : 1 , int volatile* : 2 , int* : 3 , default: -1 )

void foo() {
	COMPLIANT1(0);
	COMPLIANT2(0);
}

void exceptionDemo(int const *p) {
	_Static_assert(EXCEPTION(p) == 1, "must be const");
}

チェック情報

グループ: 総称選択
カテゴリ: 推奨
AGC カテゴリ: 推奨

バージョン履歴

R2024a で導入


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.