どのコンパイラも、ビルド後に多数の警告を報告する可能性があります。警告をエラーとして扱う設定にしない限り、これらの警告がコードのコンパイルを妨げることはありません。無視するのではなく、時間を取って確認してください。コンパイラ警告は、そうしなければ実行時まで表面化しない潜在的なバグを示していることがよくあります。
Clangは、多くの便利な機能を備えたC/C++/Objective-Cコンパイラです。主なエンドユーザー向け機能は次のとおりです。
- 高速なコンパイルと低メモリ使用量。
- 表現力の高い診断。
- GCCとの互換性。
この記事では、Clangの表現力の高い診断と、それをVisual C++プロジェクトで取得する方法に焦点を当てます。
Clangチームは、できるだけ明確で有益なエラーメッセージを提供することを目指しています。コマンドラインコンパイラとして可能な限り使いやすいものにしようと努めています。そのために、Clangはコード内の問題箇所を正確に指摘します。これは、エラー情報を使いやすいメッセージへ加工する診断エンジンによって実現されています。
Clang診断の利点を確認するため、最小限のC++ソースファイルをVisual C++とClangの両方でコンパイルし、報告される警告を比較してみましょう。両方のコンパイラですべての警告を有効にします。

Microsoft C++コンパイラは次の警告を報告します。
- warning C4100: ‘n’:参照されていない仮パラメータ
Clangは3つの警告を報告します。
- 関数 ‘Print’ に以前のプロトタイプがありません
- 旧式のキャストが使用されています
- 未使用のパラメータ ‘n’
Clangの興味深い点は、コーディングのベストプラクティスに関する診断も報告することです。たとえば、「関数 Print に以前のプロトタイプがありません」という警告は、Print が static 関数として宣言されていないため報告されます。つまり、別のソースファイルから使用される可能性があり、その場合は宣言をヘッダーファイルに置くことが推奨されます。
Clangの診断をより具体的に理解するため、オープンソースのC++プロジェクトをClangとMicrosoftコンパイラの両方でコンパイルし、報告される警告の種類を比較してみましょう。
例として「7-Zip」プロジェクトを使い、Gui.vcproj モジュールだけをコンパイルします。外部インクルードファイルではなく、プロジェクトのソースコードに関する警告だけに焦点を当てます。
Microsoftコンパイラは次の種類の警告を報告します。
- データメンバーの後にバイトパディングが追加されました。
- 変換の問題。
- 関数がインライン化されませんでした。
- クラスに仮想関数がありますが、デストラクタが仮想ではありません。
- Visual C++ 7.1 以降、Catch(…) の意味論が変更され、構造化例外(SEH)は捕捉されなくなりました。
- キャストの問題。
- 列挙型 ‘NCommandType::EEnum’ の switch で、列挙子 ‘kInfo’ が case ラベルで明示的に処理されていません。
- ‘GetVersionExA’ は非推奨として宣言されています。
- 旧式のキャストが使用されています
- フィールド ‘MinLen’ の初期化子がありません
- マクロが使用されていません
- 宣言にグローバルコンストラクタが必要です
- 宣言に終了時デストラクタが必要です
- 変換の問題
- キャストの問題
- 列挙値 ‘kWithoutPrompt’、‘kAutoRename’、‘kAutoRenameExisting’ が switch で処理されていません
- ?: のオペランドで符号性が変化します:‘const int’ から ‘unsigned int’ へ
- 宣言がローカル変数をシャドウしています
- ISO C++11では、文字列リテラルから ‘LPSTR’(別名 ‘char *’)への変換は許可されていません
- 関数に以前のプロトタイプがありません
- 比較の問題
- ‘GetVersionExA’ は非推奨として宣言されています
- 動的例外指定は非推奨です
- ‘||’ 内で ‘&&’ が使用されています
- ‘CBenchRandomGenerator’ にはアウトオフラインの仮想メソッド定義がないため、その vtable はすべての翻訳単位で生成されます
- 仮想関数を持ち、非仮想デストラクタを持つ ‘CBenchmarkInStream’ に対して delete が呼び出されました
- ‘CBenchmarkInStream’ には仮想関数がありますが、非仮想デストラクタです
- 等値比較の結果が使用されていません
- ‘INT_PTR’ 型(別名 ‘int’)の変数の値を、その変数自身に明示的に代入しています
- dangling else を避けるために明示的な中括弧を追加してください
ご覧のとおり、ClangはMicrosoftコンパイラよりも有用な警告を多く報告します。その一部は通常、静的解析ツールだけが報告するものです。これらの警告は多くのバグを明らかにする可能性があるため、真剣に受け止める価値があります。
Visual C++プロジェクトでClang診断を取得するには?
Clang診断は、開発者がC/C++ソースコードの品質を向上させるのに役立ちます。そのため、Visual C++プロジェクトでも利用できると便利です。
1つ目の方法は、Clangを使ってプロジェクトをコンパイルすることです。次の MSDNの記事 では、VSでClangをコンパイラとして使用する方法が説明されています。
2つ目の方法は、 CppDependを使ってVisual Studioプロジェクトを解析することです。CppDependはClangをフロントエンドパーサーとして使用し、その診断をすべて報告します。CppDependは オープンソースコミュニティには無料で提供されています。
次のクエリは、すべてのClang診断を返します。

7-ZipアプリケーションのGuiプロジェクトはコードが1万行しかありませんが、診断は1,186件あります。中規模・大規模プロジェクトでは、数千件の診断が出る可能性があります。その場合は、フィルタリングして特定の種類の警告だけを取得すると便利です。
たとえば、前のクエリを変更して、非推奨の使用法に関する警告だけを取得できます。

まとめ:
警告は潜在的なバグを示すことが多いため、無視すべきではありません。Clangは、コーディングのベストプラクティスに関するものを含め、多くの有用な診断を報告します。これらの警告に対処することで、プロジェクトのソースコード品質を高められます。
