yohhoyの日記

技術的メモをしていきたい日記

-Wnoexceptオプション

gcc(g++)では、C++関数への noexcept 指定子付け忘れを警告するオプションが提供される。Clangでは未実装。

要約:

  • 評価結果がfalseとなる noexcept 式オペランドのみが警告対象。残念ながら非常に限定的。
  • 地味にペナルティを受ける「ムーブコンストラクタ/代入演算子への noexcept 指定忘れ」の検知にはあまり期待できない。*1

gcc 4.6.0で追加された警告オプション。

-Wnoexcept (C++ and Objective-C++ only)
 Warn when a noexcept-expression evaluates to false because of a call to a function that does not have a non-throwing exception specification (i.e. throw() or noexcept) but is known by the compiler to never throw an exception.

https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html

下記コードではムーブコンストラクタ(X::X(X&&))への noexcept 指定忘れを検知できる。

struct X {
  X() {}
  X(const X&) = delete;   // コピー禁止
  X(X&&) /*noexcept*/ {}  // ムーブのみ許可(noexcept無し)
};

int main()
{
  X x;
  std::cout << noexcept(X{std::move(x)});
} // 出力: 0

gcc 4.7.3のエラーメッセージ(明示的な -Wnoexcept オプション指定が必要):

In function 'int main()':
warning: noexcept-expression evaluates to 'false' because of a call to 'X::X(X&&)' [-Wnoexcept]
warning: but 'X::X(X&&)' does not throw; perhaps it should be declared 'noexcept' [-Wnoexcept]

関連URL

*1:例えば、標準 vector コンテナと noexcept 指定なしムーブ操作との関係が挙げられる。詳細はHow to enforce move semantics when a vector grows?なぜstd::vector<>はnoexceptでないmove constructorを呼ばないのかを参照のこと。