__attribute __((warn_unused_result))と同等のMSVC?

2010年11月19日に質問されました。  ·  閲覧回数 9.7k回  ·  ソース

Paul R picture
2010年11月19日

__attribute__ ((warn_unused_result))は、関数によって返されるエラーコードを無視しないように開発者を促す手段として非常に役立つと思いますが、MSVC、gcc、およびICCなどのgcc互換コンパイラで動作するためにこれが必要です。 Microsoft Visual Studio C / C ++コンパイラには同等のメカニズムがありますか? (私はこれまで運がなかったのでMSDNをくぐり抜けてみました。)

回答

Albert picture
2014年03月31日
14

_Check_return_です。 参照してくださいここで同様の注釈の例については、とここで関数の動作のために。 MSVC2012以降でサポートされています。

例:

_Check_return_
int my_return_must_be_checked() {
    return 42;
}
Paul R picture
2014年03月31日
12

MSVC2012以降の更新

SAL静的コード分析を使用する場合、MSVCがVisual Studio 2012の時点で注釈_Check_return_をサポートするようになったことを指摘してくれた@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 (または-analyze )スイッチが必要であり、Visual StudioIDEを使用する場合は同等のスイッチが必要になることにも注意してください。 これはまた、ビルドをいくらか遅くする傾向があります。

John Dibling picture
2010年11月19日
5

VisualStudioの一部のエディションには、以前はPREFast (現在は単に「C / C ++のコード分析」と呼ばれています)と呼ばれていた静的分析ツールがパッケージ化されています。 PREFastは、注釈を使用してコードをマークアップします。 それらの注釈の1つであるMustCheckは、探していることを実行します。

Timo Geusch picture
2010年11月19日
3

私の知る限り、MSコンパイラには同等のプラグマまたは属性がありません。適切な警告レベルでオプティマイザをオンにした場合に、変数に対してのみ「未使用」タイプの警告が表示されます。

nemequ picture
2018年03月25日
1

他の人が言及しているSALアノテーションはMSVCの正しい答えだと思いますが、MSVC、GCC、およびGCC互換のコンパイラよりも移植性に関心がある人もいると思います。

まず、GCCは3.4以降warn_unused_resultのみをサポートします。 __GNUC__が定義されているかどうかを確認するだけでなく、 __GNUC__ / __GNUC_MINOR__の値を確認することもできます

いくつかのコンパイラはGCCスタイルの関数属性をサポートしており、 __GNUC__とその仲間を定義する場合としない場合があります。

  • Clang( __has_attribute(warn_unused_result) )、およびそれに基づくコンパイラ(emscripten、xlc 13 +、armclangなど)。ただし、AFAIKでは常に少なくともGCC 4.2になりすますため、明示的なものはおそらく必要ありません。チェック。
  • Intelは常に__GNUC__定義しているわけではありません( -no-gccフラグを参照)。 彼らがいつそれをサポートし始めたのかはわかりませんが(彼らのドキュメントはひどく不足しています)、16.0 +が安全であることは知っています。
  • TI8.0 +はそれをサポートします
  • --gccが渡されると、TI7.3 +はそれをサポートします。 __TI_GNU_ATTRIBUTE_SUPPORT__は、そのときに定義されます。
  • Oracle Developer Studio 12.6+は、CではなくC ++モードでサポートします。
  • PGIはC ++モードでそれをサポートします。 AFAICTは文書化されていないため、いつ追加されたかはわかりません(#1650-D)が、17.10以降には間違いなく存在します。 Cモードでは黙って無視され、いつか実装されることを願っています。

さらに、C ++ 17は[[nodiscard]]属性を追加します。 C ++ 17モードで[[nodiscard]]をサポートするバージョンのGCC / clangの場合、C ++ 11以降のモードでも[[gnu::nodiscard]]を使用できますが、マクロの背後に隠している場合は、 __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マクロを取り除き、ロジックをそれほど問題なくコピーできるはずです。 そうすることを選択した場合は、おそらくリポジトリ内のバージョンに基づいてポートを作成する必要があります。これは、この回答を新しい情報で最新の状態に保つことを覚えておく可能性がはるかに低いためです。