次のコードは、GCC と Clang の両方で警告を生成します。
int main() {
unsigned n = 0;
return ( n < 0 ) ? 1 : 0;
}
警告は次のとおりです。
$ g++-4.7 -std=c++11 -O3 -Wall -Wextra t.cc -o t
t.cc: In function ‘int main()’:
t.cc:3:16: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
$ clang++-3.2 -std=c++11 -O3 -Wall -Wextra t.cc -o t
t.cc:3:14: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
return ( n < 0 ) ? 1 : 0;
~ ^ ~
1 warning generated.
$
ここまでは順調ですね。ここで、変数を次のように変更しますconst
。
int main() {
const unsigned n = 0;
return ( n < 0 ) ? 1 : 0;
}
そして、両方のコンパイラが突然、警告なしでコードをコンパイルできるようになりました。
$ g++-4.7 -std=c++11 -O3 -Wall -Wextra t.cc -o t
$ clang++-3.2 -std=c++11 -O3 -Wall -Wextra t.cc -o t
$
質問:なぜこれが起こるのですか? 変数が警告を抑制する理由はありますか? const
GCCとClangの両方が同意する場合、何かを学ぶ必要がある可能性が高いと思われるため、バグレポートを投げることをためらっています:)
編集:コンパイラの定数の折りたたみが関係している可能性がありますが、動作を説明するには不十分です。最初の例 ( なしconst
) では、コンパイラは値を認識しており、値が変更されないことを認識しています。アセンブラーの出力を確認したところ、コンパイラーは定数の折りたたみを行いますが、おそらく式を見て、それが符号なしの型であることを知っているときに変数を既知の定数に置き換える前に、警告が生成されます。つまり、追加するとこの動作が変わるのはなぜですか? 最初の例で警告が出た場合、2 番目の例でも警告を出すことができるはずだと思います。( n < 0 )
n
const