web-dev-qa-db-ja.com

徹底的かつ詳細なg ++警告を有効にするフラグ

Cでgccの下にあることが多いので、次の一連の警告フラグから始めます(複数のソースから苦労して組み立てられます)。

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

この警告のセットを使用して(少なくともデバッグバージョン)ビルドし、可能な限りすべて(通常はすべて)を修正し、フラグが関連していないか修正できない場合にのみ削除します(ほとんどの場合)。コンパイル中に離れる必要がある場合は、-Werrorも追加することがあります。

私はただC++を取り上げています(そうです、私は15年遅れています)。そして、私は右足から始めたいです。

私の質問は次のとおりです。誰かがg++の下にC++用の完全な警告フラグのプリコンパイルされた同様のセットを持っていますか? (それらの多くが同じになることを知っています。)

109

D'oh、元の検索のすべてで、警告をsuppressする方法についての投稿の99%を(恐ろしく十分に)見つけましたが、私はただ出会いました- このコメント 、この素敵なフラグのセットがあります(関連性が低いものもあります):

とクロスチェック:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

だから、それは良い出発点だと思います。これがだまされたことに気づかなかったが、少なくともそれは深く埋まっていた。 :-)

35

調べてみると、警告の最大レベルを取得する必要があるインクルードの最小限のセットが見つかりました。次に、そのリストから、実際に悪いことが起こっていることを実際には示していない、または実際のビルドで使用するには誤検知が多すぎると感じる一連の警告を削除しました。除外したそれぞれが除外された理由についてコメントしました。これは、推奨される警告の最終的なセットです。

_-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused_

存在する疑わしい警告:

  • _-Wno-unused_を含めるのは、後で使用することがわかっている変数を持っていることが多いが、まだ機能が記述されていないためです。それに関する警告を削除することで、物事の実装を時折延期するという好みのスタイルで書くことができます。クラックをすり抜けないようにするために、時々オフにするのが便利です。

  • _-Wdisabled-optimization_は、強力なユーザー設定設定のようです。私はこれを自分のビルドに追加しました(明白な理由で最適化されたビルドの場合のみ)、それは何も表示されなかったので、少なくとも私のコーディング方法では、特におしゃべりな警告ではないようです。 (この警告を引き起こすコードが必ずしも間違っているわけではありませんが)私はそれを含めています。 gccが、私が書いたようにコードを最適化できないと言っている場合、それを書き換えることを検討する必要があります。この警告をトリガーするコードは、よりモジュール化されたものの恩恵を受ける可能性があると思うので、コードは技術的に間違っていないかもしれませんが(おそらく)、スタイル的にはそうです。

  • _-Wfloat-equal_は、安全な等価比較(特に、計算されていない値-1との比較)を警告します。これを使用する私のコードの例は、floatのベクトルがあることです。このベクトルを調べて、まだ評価すべき要素がいくつかあるので、それらを-1.0fに設定します(私の問題は正数のみを使用しているため、-1は領域外です)。後で-1.0fの値を更新します。別の操作方法には簡単に役立ちません。ほとんどの人はこの問題を抱えておらず、浮動小数点数の正確な数値の比較はおそらくエラーであると思われるので、デフォルトのリストに含めています。

  • _-Wold-style-cast_には、使用しているライブラリコードに多くの誤検知があります。特に、ネットワークで使用されるhtonlファミリーの関数、および私が使用しているRijndael(AES)暗号化実装には、警告されている古いスタイルのキャストがあります。これらの両方を置き換えるつもりですが、不満を言うコードが他にあるかどうかはわかりません。ただし、ほとんどのユーザーはおそらくデフォルトでこれをオンにしているはずです。

  • _-Wsign-conversion_は難しいものでした(そしてほとんどリストを作成しませんでした)。私のコードで有効にすると、大量の警告(100以上)が生成されました。それらのほとんどすべてが無実でした。ただし、特定の問題の領域では、通常、大量の整数除算のために符号なしの値を使用するとわずかな効率の向上が得られますが、私は確信が持てないところで符号付き整数を使用するよう注意しました。符号付き整数を誤って符号なし整数に昇格してから除算することを心配していたため、この効率を犠牲にしました(加算、減算、乗算とは異なり、安全ではありません)。この警告を有効にすると、ほとんどの変数を無署名の型に安全に変更し、他の場所にいくつかのキャストを追加できました。警告はそれほど賢くないため、現在は少し使いにくいです。たとえば、unsigned short + (integral constant expression)を実行すると、その結果は暗黙的にintに昇格されます。その後、安全であっても、その値をunsignedまたは_unsigned short_に割り当てると、潜在的なサインの問題について警告します。これは、ほぼすべてのユーザーにとって間違いなく最もオプションの警告です。

  • _-Wsign-promo_:_-Wsign-conversion_を参照してください。

  • _-Wswitch-default_は無意味なようです(すべての可能性を明示的に列挙した場合、常にデフォルトのケースが必要になるとは限りません)。ただし、この警告を有効にすると、おそらく良いアイデアになる可能性があります。リストされた可能性以外のすべてを明示的に無視したい場合(ただし、他の数値も可能です)、_default: break;_を入れて明示的にします。すべての可能性を明示的に列挙する場合、この警告をオンにすると、assert(false)などを配置して、考えられるすべてのオプションを実際にカバーしたことを確認できます。問題の領域が何であるかを明示的に示し、プログラムでそれを強制します。ただし、どこでもassert(false)を貼り付けるだけで注意する必要があります。デフォルトの場合は何もしないよりはましですが、通常のアサートでは、リリースビルドでは機能しません。つまり、ネットワーク接続や絶対的な制御ができないデータベースなどから取得した数値を検証するために、これに頼ることはできません。例外または早期復帰は、それを処理する最良の方法です(ただし、デフォルトのケースが必要です!)。

  • _-Werror_は私にとって重要なものです。複数のターゲットを備えたマルチスレッドビルドで大量のコードをコンパイルする場合、簡単に警告を逃すことができます。警告をエラーに変えることで、私はそれらに気付くことができます。

次に、上記のリストに含まれていない一連の警告がありますが、それらは有用であるとは思わなかったためです。これらは警告と、デフォルトリストにそれらを含めない理由に関する私のコメントです。

存在しない警告:

  • _-Wabi_は、異なるコンパイラのバイナリを結合していないため、必要ありません。とにかくそれでコンパイルしようとしましたが、トリガーしませんでしたので、不必要に冗長に見えることはありません。

  • _-Waggregate-return_は、私がエラーと見なすものではありません。たとえば、クラスのベクトルで範囲ベースのforループを使用するとトリガーされます。戻り値の最適化は、この悪影響を処理する必要があります。

  • _-Wconversion_はこのコードでトリガーします:_short n = 0; n += 2;_ intへの暗黙的な変換は、ターゲットタイプに変換されたときに警告を発生させます。

  • _-Weffc++_には、すべてのデータメンバーが初期化リストで初期化されていない場合の警告が含まれます。私は多くの場合これを意図的に行わないので、警告のセットは散らかりすぎて有用ではありません。ただし、たまに電源を入れて、他の警告(基本クラスの非仮想デストラクタなど)をスキャンすると便利です。これは、単独の警告ではなく、警告のコレクション(_-Wall_など)としてより便利です。

  • _-Winline_は存在しません。なぜなら、ヘッダーで関数をインラインで定義するためだけに、最適化のためにinlineキーワードを使用していないからです。オプティマイザが実際にインライン化するかどうかは気にしません。この警告は、クラス本体で宣言された関数(空の仮想デストラクタなど)をインライン化できない場合にも文句を言います。

  • プリコンパイル済みヘッダーを使用していないため、_-Winvalid-pch_がありません。

  • _-Wmissing-format-attribute_は、gnu拡張機能を使用しないため使用されません。 _-Wsuggest-attribute_および他のいくつかについても同じ

  • 存在しないことで注目に値するのは_-Wno-long-long_です。 _-std=c++0x_(GCC 4.7の_-std=c++11_)でコンパイルします。これには_long long_整数型が含まれます。 C++ 98/C++ 03にこだわっている人は、警告リストからその除外を追加することを検討するかもしれません。

  • _-Wnormalized=nfc_はすでにデフォルトのオプションであり、最良のようです。

  • _-Wpadded_は、クラスのレイアウトを最適化するために時々オンになりますが、すべてのクラスが最後にパディングを削除するのに十分な要素を持っているわけではないため、オンのままではありません。理論的には、「無料」の追加変数を取得できましたが、それを維持するための余分な努力の価値はありません(クラスサイズが変更された場合、以前に無料の変数を削除するのは簡単ではありません)。

  • _-Wstack-protector_を使用しないため、_-fstack-protector_は使用されません

  • _-Wstrict-aliasing=3_は_-Wall_によってオンになり、最も正確ですが、レベル1および2でさらに警告が表示されるようです。理論的には、レベルが低いほど「より強い」警告になりますが、誤検知が多くなります。私自身のテストコードは、3つのレベルすべてできれいにコンパイルされました。

  • _-Wswitch-enum_は、私が望んでいる動作ではありません。すべてのswitchステートメントを明示的に処理する必要はありません。言語に、指定されたswitchステートメントでこれをアクティブにするメカニズムがあれば役立ちます(enumへの将来の変更が必要なすべての場所で処理されるようにするため)が、「all-or-nothing」設定ではやり過ぎです。

  • _-Wunsafe-loop-optimizations_は、あまりにも多くの偽の警告を引き起こします。これを定期的に適用し、結果を手動で確認すると便利な場合があります。一例として、ベクトル内のすべての要素をループして一連の関数を適用すると、コードでこの警告が生成されました(範囲ベースのforループを使用)。 const std :: stringのconst配列のコンストラクターに対する警告もあります(ユーザーコードのループはありません)。

  • _-Wzero-as-null-pointer-constant_および_-Wuseless-cast_はGCC-4.7のみの警告で、GCC 4.7に移行するときに追加します。

この調査の結果、gccでいくつかのバグレポート/機能強化リクエストを提出したので、最終的には「含める」リストから「含める」リストにさらに多くの警告を追加できることを願っています。このリストには、このスレッドで言及されているすべての警告が含まれています(さらにいくつか余分に考えています)。この投稿で明示的に言及されていない警告の多くは、私が言及している別の警告の一部として含まれています。この投稿から完全に除外されている警告に誰かが気づいたら、教えてください。

edit:いくつか見落としていたようです(これを追加しました)。実際には http://gcc.gnu.org に2番目のページがありますが、これは非常によく隠されています。 一般的な警告オプション および C++オプション(警告のために下にスクロール)

119
David Stone

それらのいくつかは、すでに-Wallまたは-Wextraに含まれています。

Cの適切な基本セットアップは次のとおりです。

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

およびC++の場合

-ansi -pedantic -Wall -Wextra -Weffc++

-Werrorにはいらいらがあるため、C++の-Weffc++をスキップします)

11
Let_Me_Be

試してみる

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

これは迅速で汚れた開始であり、確実に調整が必要になります。 1つには、言語に適した名前(たとえば、C++の場合はg++)でコンパイラを呼び出しても、その言語には適用されない警告が表示されます(コンパイラーは手を放し、警告を削除するまで続行を拒否してください)。

もう1つは、-Werrorに追加したことです。警告を修正しないのであれば、なぜそれらをオンにしたいのですか?リストから警告を削除することもできます。 (たとえば、C++では-Waggregate-returnをほとんど使用しません。)

他のパフォーマンス関連オプション(-Wstack-protector)がなければ、いくつかの警告は何もしません。 -fdiagnostics-show-optionとGCCマニュアルは友達です。

ところで、いくつかの警告は相互に排他的です。特に、-Wtraditionalとともに-Wold-style-definitionおよび-Werrorを使用すると、コンパイルされません。

2

私のClionのCmakeLists.txtで

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
0
snr