__attribute__ ((warn_unused_result))
関数によって返されるエラーコードを無視しないように開発者を促す手段として非常に役立つことがわかりましたが、MSVC、およびgccやICCなどのgcc互換コンパイラで動作するためにこれが必要です。Microsoft Visual Studio C / C ++コンパイラには同等のメカニズムがありますか?(これまでのところ、運が悪かったので、MSDNをくぐり抜けてみました。)
5 に答える
MSVC2012以降の更新
_Check_return_
SAL静的コード分析を使用する場合にMSVCがVisualStudio2012の時点で注釈をサポートするようになったことを指摘してくれた、@Albertに感謝します。他の人に役立つ可能性のあるクロスプラットフォームマクロを含めることができるように、この回答を追加しています。
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define CHECK_RESULT _Check_return_
#else
#define CHECK_RESULT
#endif
gcc et alとは異なり、(a)MSVCは関数の宣言と定義の両方に注釈を付ける必要があり、(b)注釈は宣言/定義の先頭にある必要があることに注意してください(gccはどちらかを許可します)。したがって、通常、使用法は次のようにする必要があります。
// foo.h
CHECK_RETURN int my_function(void); // declaration
// foo.c
CHECK_RETURN int my_function(void) // definition
{
return 42;
}
コマンドラインからコンパイルする場合は/analyze
(または)スイッチ
が必要であり、VisualStudioIDEを使用する場合は同等のスイッチが必要になることにも注意してください。-analyze
これはまた、ビルドをいくらか遅くする傾向があります。
私の知る限り、MSコンパイラには同等のプラグマまたは属性がありません。適切な警告レベルでオプティマイザをオンにした場合に取得できる「未使用」タイプの警告は、変数に対するものだけです。
他の人が言及しているSALアノテーションは、MSVCの正しい答えだと思いますが、MSVC、GCC、およびGCC互換のコンパイラよりも移植性に関心がある人もいると思います。したがって…</ p>
まず、GCCはwarn_unused_result
3.4以降のみをサポートします。が定義されているかどうかを確認するだけでなく、 /
の値を確認することもできますが、現時点では、3.4より前のバージョンのGCCを使用している人を想像するのは困難です。__GNUC__
__GNUC_MINOR__
__GNUC__
いくつかのコンパイラはGCCスタイルの関数属性をサポートしており、次のように定義する場合としない場合があります__GNUC__
。
- Clang(でチェック
__has_attribute(warn_unused_result)
)、およびそれに基づくコンパイラ(emscripten、xlc 13+、armclangなど)。ただし、AFAIKでは常に少なくともGCC 4.2になりすますため、明示的なチェックはおそらく必要ありません。 - Intelは常に定義しているわけではありません
__GNUC__
(-no-gcc
フラグを参照)。彼らがいつそれをサポートし始めたかはわかりませんが(彼らのドキュメントはひどく不足しています)、16.0+が安全であることは知っています。 - TI8.0+はそれをサポートします
- TI 7.3+は、-gccが渡されたときにそれをサポートします。
__TI_GNU_ATTRIBUTE_SUPPORT__
あるときに定義されます。 - Oracle Developer Studio 12.6+は、CではなくC++モードでサポートします。
- PGIはC++モードでそれをサポートします。AFAICTは文書化されていないため、いつ追加されたかはわかりませんが(#1650-D)、17.10以降には間違いなく存在します。Cモードでは黙って無視され、いつか実装されることを願っています。
さらに、C++17は属性を追加し[[nodiscard]]
ます。[[nodiscard]]
C++17モード
でサポートするバージョンのGCC/clangの場合[[gnu::nodiscard]]
、C ++ 11以降のモードでも使用できますが、マクロの背後に隠している場合は、代わりにそうする理由がわかりません。を使用するだけ__attribute__((__warn_unused_result__))
です。
まとめると、Hedleyには次のようなHEDLEY_WARN_UNUSED_RESULTマクロがあります。
#if defined(__cplusplus) && (__cplusplus >= 201703L)
# define HEDLEY_WARN_UNUSED_RESULT [[nodiscard]]
#elif \
HEDLEY_GNUC_HAS_ATTRIBUTE(warn_unused_result,3,4,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
(HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#elif defined(_Check_return_) /* SAL */
# define HEDLEY_WARN_UNUSED_RESULT _Check_return_
#else
# define HEDLEY_WARN_UNUSED_RESULT
#endif
Hedley(パブリックドメイン/ CC0)を使用したくない場合は、内部のHedleyマクロを取り除き、ロジックをそれほど問題なくコピーできるはずです。そうすることを選択した場合は、おそらくリポジトリ内のバージョンに基づいてポートを作成する必要があります。これは、この回答を新しい情報で最新の状態に保つことを覚えている可能性がはるかに低いためです。