とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

VC++10 の<stdint.h>, <cstdint>はバグっている (3)

Microsoft Visual C++ 2010 の , ヘッダにはさらにバグがあります。
本来これらのヘッダはC言語C++とで処理を切り分けなければなりません。規格(JIS X 3010:2003)には次のようにあります。

7.18.2 幅を指定する整数型の限界値 7.18.2 の各箇条でのオブジェクト形式マクロ(217)は,
で宣言されている型の最小値及び最大値を示す。
(217) C++の処理系では,を取り込む前に__STDC_LIMIT_MACROS が定義されている場合
に限り,これらのマクロを定義しなければならない。

(snip)
7.18.3 他の整数型の限界値 次のオブジェクト形式マクロ(218)は,他の標準ヘッダで定義された型に対応
する整数型の最小値及び最大値を示す。
(218) C++の処理系では,を取り込む前に__STDC_LIMIT_MACROS が定義されている場
合に限り,これらのマクロを定義しなければならない。

(snip)
7.18.4 整数定数のマクロ 7.18.4 の各箇条での関数形式マクロ(220)は,で定義された型に対
応する整数型をもつオブジェクトの初期化に使用することができる,整数定数に展開する。
(220) C++の処理系では, を取り込む前に__STDC_CONSTANT_MACROS が定義されている
場合に限り,これらのマクロを定義しなければならない。

C++ に限り __STDC_LIMIT_MACROS, __STDC_CONSTANT_MACROS マクロ定義の有無で,定義されるマクロに違いが出るようにしなければなりません。
しかし,VC++10 ではそうなっていません。以下,バグ再現コード。

#include<cstdint>
#include<iostream>
int main(){
 using std::cout;
 using std::endl;
 cout << INT8_MIN << endl    // C++ では __STDC_LIMIT_MACROS マクロが定義されていないと
  << INT_LEAST16_MAX << endl // これらのマクロを使えないはずで,
  << UINT_FAST32_MAX << endl // コンパイルエラーになるはずだが…。
  << INTPTR_MIN << endl      //
  << INTMAX_MAX << endl      // VC++10 の <stdint.h>, <cstdint> では
  << PTRDIFF_MIN << endl     // __STDC_LIMIT_MACROS マクロを定義することなく
  << SIG_ATOMIC_MAX << endl  // コンパイルに通ってしまう…。
  << WCHAR_MIN << endl
  << WINT_MAX << endl;

 std::cout
  << INT8_C(0) << endl       // C++ では __STDC_CONSTANT_MACROS マクロが定義されていないと
  << INT16_C(0) << endl      // これらのマクロを使えないはずで,
  << INT32_C(0) << endl      // コンパイルエラーになるはずだが…。
  << INT64_C(0) << endl      // VC++10 の <stdint.h>, <cstdint> では
  << INTMAX_C(0) << endl     // __STDC_CONSTANT_MACROS マクロを定義することなく
  << UINTMAX_C(0) << endl;   // コンパイルに通ってしまう…。
}

すんなりコンパイル通ってしまいます。あちゃー…。
元のソースは修正して

#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)

#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)

で,該当箇所を囲む必要がありますね。