GCCの警告(implicit narrowing conversion)

2ちゃんねる GCCスレより。

116 名前:デフォルトの名無しさん 投稿日:04/08/30 11:43
long longの変数をint型の変数に代入した時、警告するようなオプションってありますでしょうか?

integer overflow を起こしていそうな場所の目星をつけるのに、確かにこういう警告が可能だと嬉しい。「long long から int」に限定しているのも、気持ちはよくわかる。例えば、LP64環境、あるいはoff_tが64bitの環境(例: g++ -D_FILE_OFFSET_BITS=64)で、「ファイルサイズやディスクサイズを、いつのまにか32bit幅の変数に代入してしまう」という類のミスは色々な場所で良く見かけるので、そういうのを検出したいのかなと予想します。そういう単純なミスであっても、真面目に検査すると結構手間。コンパイラがやってくれるなら時間が節約できて私もとても嬉しいです。


レスは2つ。

  1. boost::numeric_cast使え
  2. GCC-3.4.0用のパッチがあるよ

らしい。前者はまぁ冗談ということで流して、後者。議論はここで、パッチはここ。2004/06の投稿です。結論からいうと、そのパッチを使っても警告されません。


GCCのMLでの議論の内容を要約すると、「A: 値が変化してしまうようなimplicit conversionを全て警告する方法はない?」「B: 4年前から議論があるけどパッチはまだないよ」「A: こんなんでどう?もうあと4年待つよりは何かあったほうがマシじゃない?REAL_TYPEとINTEGER_TYPEの変換しか警告しないけど。」「B: パッチだけじゃ検討対象外。ドキュメントやテストケースも作って」といったところ。INTERGER_TYPE同士の変換はノーチェックなんで、このパッチじゃ>>116さんの用途にはマッチしないんですよね*1


数年前の議論というのは、これ

Proposals for a better -Wconversion, of use for security auditing. The new option semantics should be “warn for any implicit conversion that may change a value”; there might or might not be separate options for parts of this (change of sign; reduction of integer width; conversion of complex to real or floating to integer; conversion of floating to floating with lesser range or precision; conversion of integer to floating that can’t exactly hold all values of the integer type) (in addition to the present -Wsign-compare, which the option would imply), and the other existing warnings might or might not remain available under -Wconversion-traditional. Some cases of this are already available under existing options, but others such as assigning a signed int to an unsigned int aren’t. The same intelligence used by -Wsign-compare to avoid warning where problems cannot in fact arise would apply here.

-Wconversion をもっとマトモにしようよという話で、具体的には次のタイプの暗黙の変換(implicit conversion)を警告するようにしたいね、という提案。

  • 符号有無の異なる型への変換
  • 整数のビット幅が縮小するような変換*2
  • complex型 → real型 の変換
  • floating型 → integer型 の変換
  • floating同士の変換だが、rangeやprecisionが劣化する変換
  • integer型 → floating型 の変換だが、元のinteger型で表現できる値の全てを変換後のfloating型が保持できない変換

complex型は、C99で導入されたfloat complex, double complex, および long double complexのこと、real型は、float, double および long doubleのこと、floating型は、以上6つ全てを指していると思われます。


目的は、"seucity auditing" だと明言されていますねぇ。激しく実装希望です。また、セキュリティ関連のMLでも、GCCの不備を指摘している人がいます


splintを使えば大部分警告されると思いますが、例によってC++には対応していないので、私のまわりでは使えそうにありません。一応、Cのソースコードで確認してみました↓

$ cat aaa.c
static int y, z;
void bar(int w);

int foo(long long  x) {
        y = x;
        z = (int)x;
        bar(x);
        return x;
}

$ splint aaa.c
Splint 3.1.1 --- 17 Feb 2004

aaa.c: (in function foo)
aaa.c:5:2: Assignment of long long to int: y = x
  To ignore type qualifiers in type comparisons use +ignorequals.
aaa.c:7:6: Function bar expects arg 1 to be int gets long long: x
aaa.c:8:9: Return value type long long does not match declared type int: x

Finished checking --- 3 code warnings

明示的なcast以外はちゃんと警告されています。

*1:2ちゃんねるに投稿してみた

*2:>>116さんや私が警告して欲しいケース