PRE32-C. 関数形式マクロの呼出しのなかで前処理指令を使用しない
マクロに渡す引数に #define
、#ifdef
、#include
などの前処理指令を含めてはならない。C言語規格[ISO/IEC 9899:2011] セクション6.10.3 パラグラフ11によると、このようなコードは未定義の動作となる。
最も外側の括弧によって囲まれた前処理字句の列は、関数形式マクロの実引数の並びを形成する。並びの中の個々の実引数は、コンマ前処理字句によって区切る。ただし、内側に対をなす括弧がある場合、その中のコンマ前処理字句は、実引数を区切るものではない。実引数の並びの中に、ほかの場合であれば前処理指令として働く前処理字句がある場合、その動作は未定義とする。
C言語規格の附属書J、未定義動作93も参照。
このルールは、マクロにより実装されているかどうか不明な関数の引数内で使われている前処理指令にも適用される。たとえば、memcpy()
、printf()
、assert()
などの標準ライブラリ関数はマクロとして実装されている可能性がある。
違反コード
以下の違反コード例 [GCC Bugs] では、memcpy()
にプラットフォーム固有の引数を指定するために、前処理指令を使用している。しかし、memcpy()
がマクロにより実装されていた場合、このコードは未定義の動作となる。
#include <string.h>
void func(const char *src) {
/* ソース文字列を検証しサイズを計算 */
char *dest;
/* コピー先文字列のために malloc() */
memcpy(dest, src,
#ifdef PLATFORM1
12
#else
24
#endif
);
/* ... */
}
適合コード
次の適合コード [GCC Bugs] では、適切な memcpy()
呼び出しの判定を行っている。
#include <string.h>
void func(const char *src) {
/* ソース文字列を検証しサイズを計算 */
char *dest;
/* コピー先文字列のために malloc() */
#ifdef PLATFORM1
memcpy(dest, src, 12);
#else
memcpy(dest, src, 24);
#endif
/* ... */
}
リスク評価
マクロの引数に前処理指令が含まれていると未定義の動作となる。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
PRE32-C |
低 |
低 |
中 |
P2 |
L3 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Astrée |
18.10
|
macro-argument-hash | 実装済み |
Axivion Bauhaus Suite |
6.9.0 |
CertC-PRE32 | 実装済み |
CodeSonar |
5.0p0
|
LANG.PREPROC.MACROARG | マクロ引数中の前処理指令 |
1.2
|
CC2.PRE32 |
実装済み |
|
LDRA tool suite |
9.7.1
|
341 S | 実装済み |
Parasoft C/C++test |
10.4.1 |
CERT_C-PRE32-a |
Arguments to a function-like macro shall not contain tokens that look like preprocessing directives |
R2018a |
Preprocessor directive in macro argument | You use a preprocessor directive in the argument to a function-like macro | |
PRQA QA-C |
9.5
|
0853 |
|
PRQA QA-C++ |
4.3 |
1072 |
|
RuleChecker |
18.10
|
macro-argument-hash | Fully checked |
参考資料
[GCC Bugs] | "Non-bugs" |
[ISO/IEC 9899:2011] | 6.10.3, "Macro Replacement" |
翻訳元
これは以下のページを翻訳したものです。
PRE32-C. Do not use preprocessor directives in invocations of function-like macros (revision 76)