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++用の完全な警告フラグのプリコンパイルされた同様のセットを持っていますか? (それらの多くが同じになることを知っています。)
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
だから、それは良い出発点だと思います。これがだまされたことに気づかなかったが、少なくともそれは深く埋まっていた。 :-)
調べてみると、警告の最大レベルを取得する必要があるインクルードの最小限のセットが見つかりました。次に、そのリストから、実際に悪いことが起こっていることを実際には示していない、または実際のビルドで使用するには誤検知が多すぎると感じる一連の警告を削除しました。除外したそれぞれが除外された理由についてコメントしました。これは、推奨される警告の最終的なセットです。
_-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++オプション(警告のために下にスクロール)
それらのいくつかは、すでに-Wall
または-Wextra
に含まれています。
Cの適切な基本セットアップは次のとおりです。
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
およびC++の場合
-ansi -pedantic -Wall -Wextra -Weffc++
(-Werror
にはいらいらがあるため、C++の-Weffc++
をスキップします)
試してみる
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
を使用すると、コンパイルされません。
私の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)