ラベル cpp の投稿を表示しています。 すべての投稿を表示
ラベル cpp の投稿を表示しています。 すべての投稿を表示

2022年3月10日木曜日

Include-What-You-Use の docker image を更新しました

https://hub.docker.com/repository/docker/srzzumix/iwyu/general

表題どおりです。
今まで自分が使うようにイメージを置いといただけでしたが、各 clang バージョン x Ubuntu バージョン x Multi Arch(amd64/arm64) でビルドしておいておきました。
Include What You Use は C/C++ の include の最適化をしてくれるツールです。
過去に記事を書いてますのでそのへんを参考にしてください。
ブログズミ: [C++] Include-What-You-Use で依存関係を確認する


ビルドは GitHub Actions で行っています。
https://github.com/srz-zumix/docker-iwyu 

今後は複数 arch 対応の需要が上がっていく気がしてるので今回から対応してみました。
複数 arch 対応の image をローカルでビルドする場合は、レジストリに push しながらなら OK らしく(ようは実行環境の arch しかローカルビルドできないって感じかな?)勉強になりました。
今まではビルドしたあとにタグつけて push してたのですが、これだと実行環境の arch しか push できなかったため、一度ビルドしたイメージからバージョン情報とかを取り出し、タグを生成してから再度 docker/build-push-action を実行してます。

これらのイメージは定期的にビルドするものでもないので手動トリガーでビルドするようになってます。
一部の組み合わせではビルド失敗したり、clang のインストールできなくて image のビルドに失敗してます。
需要があればちゃんと見てみますので、もしあれば issue に書いてください。

以上。


2021年12月16日木曜日

Visual Studio でライブラリなど外部コードの警告を出さないようにする方法

これは「C++のカレンダー | Advent Calendar 2021 - Qiita」の16日目の記事です。

はじめに

警告はときにプログラムの問題を教えてくれます。
警告は基本的にないのが望ましいです。なぜなら、野原から四葉のクローバーを探し出すのは大変だからです。(見つけた四葉は幸運をもたらすか、不幸をもたらすか。。見つけるなら早いほうがいいですよ)

CI/CD 担当をやっていると警告を直してもらうための対応とかしたりします。
警告出てたらステータスを変えて通知とか、ちょっとずつ警告をエラーにしていくとか。
ここで問題になるのは、自分たちが改変することができない SDK やライブラリの警告です。
通知で頑張ってる場合はフィルターでなんとかなるかもしれません。
as Error にしている場合は困ります。

そんな場合は自分たちのコード以外をシステムインクルード(#include <...>)し別途警告レベルを制御することで解決できます。

Visual Studio で外部コードの警告を制御する

Visual Studio では 2017 (15.6) からシステムインクルードの警告レベルを別途設定できるようになりました。「/external (外部ヘッダー診断) | Microsoft Docs」こちらの公式ドキュメントにもありますが 2017 では試験機能となっています。/external オプションに加えて /experimental:external オプションも必要になるので注意してください。2019 からは正式機能となっており、設定も専用のページができました。

さて、これを利用すれば外部コードはシステムインクルードとすることで警告がでないようにできます。試しに以下のコードで試してみました。


/external の設定

プロジェクトプロパティの「C/C++」→「外部インクルード」を開き、 /external:W0 を設定します。コード分析も外部インクルードに対して別途制御可能なので、有効にしている場合は設定しましょう。

外部インクルードディレクトリにパスを追加している場合は、システムインクルードすれば外部インクルードとして認識されます。もしただのインクルードディレクトリにパスを追加している場合は、/external:anglebracket オプションを有効にすることで外部インクルードとみなされます。(システムインクルードすれば警告でなくなると逃げ口として意図しない対応をされる可能性があるので、インクルードディレクトリの設定を変更するのをオススメします)

システムインクルードではない場合

C4390 と C4456 が出ます。

システムインクルードの場合

システムインクルードにすると警告が消えました!

消えない警告もある?

たまたま見つけたのですが、システムインクルードしたファイルの警告でも /external:W0 が効かずに警告されるケースがありました。(こういう書き方をすることはない気もしますが)
コードはこちらです。gcc/clang では警告されませんでした。(https://wandbox.org/permlink/kPn2z1MLCAvbOBny

↑は C4390/C4702 の2つ。↓は C4390 は消えるが、C4702 は消えない。

Visual Studio でシステムインクルードヘッダーの警告を厳しくする

逆にシステムインクルードの警告レベルを上げるとどうなるのでしょうか?
標準ライブラリはシステムインクルードしていると思いますが、それらのコードに警告はあるのか・・? /external:W4 にして試してみました。


結果としては警告は出ない、が警告があるのかないのかはわからない。でした。
というのも VS2017 より前から標準ライブラリの警告って見た記憶がないため(たぶん)、別途制御されているのでは?と思ったからです。
ちなみに後述してますが gcc/clang では(とあるコンパイルオプションをつけると)標準ライブラリからも警告が出ていたこともあります。
MSVC の STL は公開されているので、暇なときにビルドしてみて確認してみようかと思います。
https://github.com/microsoft/STL

gcc/clang の場合

gcc/clang の場合は古くからシステムインクルードの警告は除外されていました。
(Visual Studio が今までできてなくて 2017 でようやくという感じでした)
Wandbox で試してみたのでリンクを貼っておきます。
コードは Gist にも置いてあります。

システムインクルードではない場合

警告でます。
gcc: https://wandbox.org/permlink/MLrLASaM5o5A3UWm
clang: https://wandbox.org/permlink/x6TT2NFROSmyLhV4


システムインクルードの場合

警告でません。
gcc: https://wandbox.org/permlink/XVHXnWIMyOfDMjl3
clang: https://wandbox.org/permlink/strTYwduT4ZLH5NK

gcc/clang でシステムインクルードヘッダーの警告を有効にする

gcc/clang でもシステムインクルードの警告を有効にできます。-Wsystem-headers オプションを使います。
試しにしてみると・・

新しいコンパイラーと標準ライブラリの組み合わせだと警告でませんでした。
古いとそこそこ出ます。

gcc 9.1.0: https://wandbox.org/permlink/lhXWuNvWEJdKwJNh
gcc 8.3.0: https://wandbox.org/permlink/4dHKZKtdqmDGmXNU 
clang 6.0.0: https://wandbox.org/permlink/MaVYzrGDeT79eMZa
clang 5.0.0: https://wandbox.org/permlink/qjbmV9U2c8MxHe6A

まとめ

システムインクルードを使って外部コードの警告を除外、自身のコードの警告を取り除く/取り除いてもらうように自動化/自働化しましょう。

2021年12月9日木曜日

Facebook 改め Meta 社の静的解析ツール Infer を GitHub Actions でかける

この記事は「C++のカレンダー | Advent Calendar 2021 - Qiita」の9日目です。

Infer とは

Infer は Facebook 社改め Meta 社が作った静的解析ツールです。
今回は C++ Advent Calendar ということで C++ の静的解析ツールとして紹介しますが、Infer 自体は OCaml で書かれています。
また、C++ の他に Java/C/Objective-C の解析も可能です。

C++ の静的解析ツールというと Cppcheck や Coverity 、コンパイラ付属のものがあったりします。筆者はこれまでこれらのツールを使ってきました。
Infer は 2015 年にOSS化して公開されたのですが、ずっと使ってみたいと思いつつ機会がありませんでした。

今回こうして記事にしているのは、仕事で必要になったからとか趣味でやる気になったからではなく、社名が変わったからネタとして触ることにしました。
理由はともあれ、以下で紹介していきます!

ローカル環境で使う場合

本記事は表題どおり「GitHub Actions」で Infer を使う手順を紹介しますが、ローカル環境で実行する場合も軽く触れておきます。
まず大事なこととして、Windows 非対応です!
Mac の場合は brew install infer でインストールできます。Linux の場合はビルド済みバイナリをダウンロードするか、ソースコードビルドで使うことができます。Docker という手もあります。
詳しいことは公式の「Getting Started with Infer」を見てください。

セットアップできたら「infer run -- ビルドコマンド」のようにコマンド実行すると以下のように結果が出ます。

ビルドコマンドは対象によって変わると思いますが、コンパイラー以外にも cmake や make 、mvn などのビルドツールにも対応しています。

ビルドコマンドが bash script になっているような場合はキャプチャーするコマンドを認識できないので、--force-integration オプションで教えてあげてください。
対応している integration は --force-integration オプションのヘルプで確認できます。
e.g. infer run --force-integration clang -- build.sh

GitHub Actions で使う

では、ここから本題です。
GitHub Actions で Infer を使うために、Setup Infer action (srz-zumix/setup-infer) と Infer reviewdog action (srz-zumix/reviewdog-action-infer) を作成しました。

setup-infer

Infer を現在の環境にセットアップするアクションです。
当然ですが Windows は非対応です。また Mac の場合はバージョン指定はできず、 brew install で取得できるバージョンがインストールされます。
(要望あれば対応しようかと思いますので、issues へどうぞ)

reviewdog-action-infer

Infer の結果を reviewdog を使って PR にコメントするアクションです。
Infer の実行結果が入っている infer-out から result.txt を参照し、reviewdog を使って PR に問題をコメントします。


なぜ action を分けたのか

最初は Infer インストールや解析込みの action を書こうと思ったのですが、ビルドツールや環境はユーザーによってバラバラで、action 側ですべてに対応するのは難しいと考えてこのようになりました。

Infer の実行

上記2つの action は infer での解析処理をしませんので、ワークフローで適宜呼び出してください。
個人開発してるテストフレームワーク(iutest)の例を記載しておきます。

  infer:
    runs-on: ubuntu-latest
    needs: prepare
    steps:
      - uses: actions/checkout@v2
      - uses: srz-zumix/setup-infer@v1
      - name: infer
        run: |
          infer -- make -C test IUTEST_USE_PYTHON=0
      - name: Check Infer report
        uses: srz-zumix/reviewdog-action-infer@v1
        with:
          reporter: github-pr-review
   
結果

iutest のワークフローの結果はこちらです。
静的解析なしだと 10 分くらいのテストが、Infer ありだと 25 分弱と少し時間がかかってますが、まぁ趣味開発なので許容範囲です。

速度向上

Recommended flow for CI | Infer」こちらで CI 向けのおすすめ実行方法が書いてあります。うまくキャッシュできるのであれば --reactive オプションでキャプチャーした情報を再利用すれば早くなると思います。
reportdiff は reviewdog で同等のことができるのでどちらでも。

また --changed-files-index オプションで差分ファイルのリストを指定すれば、そのファイルの解析だけが行われるため、速度向上可能です。
ただし、C++ の場合はヘッダーファイルを指定しても解析されません。.cpp ファイルを指定しないとダメです。(※ --changed-files-index は analyze 時に有効なので capture 時間の短縮にはならない)

Infer capture/analyze TIPS
capture/analyze 中にクラッシュする場合

--skip-analysis-in-path で除外指定できるのでそれをおすすめします。
-g オプションでデバッグモードになるので原因調査ができるかもしれませんが、ストレージを圧迫するかもしれません。
(3,000 弱のソースコードファイル数からなるプロジェクトでやったら 600GB 越えたあたりでディスクフルになって PC 自体が落ちました。。)

解析途中でエラーが出る場合

--keep-going オプションを付けると続行可能です。

compile_commands.json の場合 --clang-blacklisted-flags/--clang-blacklisted-flags-with-arg は効かない

そのまんまです。特に xcodebuild の場合 infer が使う clang が知らないオプションを使ってることがあり、「error: unknown argument: '-index-store-path'」のように失敗していまいます。 infer はデフォルトで  --clang-blacklisted-flags-with-arg に -index-store-path が入ってますが、 compile_commands.json から capture をする場合は --clang-blacklisted-flags(-with-arg) オプションは考慮されないので、json ファイルの command から削除してください。

--continue-analyz

仕事のプロジェクトに Infer 掛けてみたら analyze でクラッシュするわ、エラー起こるわ、なんか応答なくなるわ、そもそも解析時間がクソ長いわ、で辛かったんですが、--continue-analyz オプションつけると続きから解析してくれるので作業が無駄になりません。
(最初に知りたかった)

.inferconfig にオプションを書ける

infer のコマンドラインオプションは .inferconfig ファイルに書いておくことができます。
ファイルの中身は JSON 形式でオプションから -- を除いた名前をキーに設定をします。

例えば、上記で紹介した --skip-analysis-in-path や、 infer の clang にインクルードパスを追加する場合は以下のように書けます。

{
    "skip-analysis-in-path": [
        "path/to/lib/xxx/src",
    ],
    "Xclang": [
        "-I /path/to/dir/include",
    ]
}
まとめ

静的解析ツールは1つかければ十分というものではないので、ぜひ試してみてください。

以上。

2021年11月17日水曜日

xcpretty で compile_commands.json を出力しても空になってしまう理由がわかった!

 1年以上前に非 CMake プロジェクトからなんとか CMake にできないかなーと思って compile_commands.json を仲介させる方法をやろうとしたけど、そもそもうまく出力できなかった理由が今日わかったんで備忘録!

原因は ccache

そのプロジェクトは ccache を利用しており、CC/CXX に ccache_wrapper.sh みたいなのを設定していました。最近 infer を試してて xcodebuild capture じゃうまくできなかったので、compile_commands.json でやろうとしたら1年ぶりに同じ罠にハマったのですが、今度は乗り越えた!圧倒的成長!!

xcpretty の parser.rb を見れば一目瞭然でした
https://github.com/xcpretty/xcpretty/blob/master/lib/xcpretty/parser.rb#L63

コンパイラー検出用の正規表現的に clang で終わるような CC じゃないと認識しれくれないかったのです。
ccache_wrapper.sh じゃなくて ccach_wrapper_clang だったらセーフだった・・

対応方法

CC/CXX はプロジェクトで設定されているので、xcconfig を食わせて CC/CXX を上書きするようにしました。

cxx.xcconfig

CC = clang
CXX = clang++
export XCODE_XCCONFIG_FILE=/path/to/dir/cxx.xcconfig 
xcodebuild -scheme XXX -project XXX.xcodeproj -configuration Debug -dry-run build | tee ./build.log | xcpretty  --report json-compilation-database --output ./compile_commands.json

ちょーすっきりした


2021年2月25日木曜日

cppcheck html report

 久しぶりに cppcheck を使ってみたら HTML レポートができるようになっていたのでメモ。

環境セットアップ

HTML レポートを作成するには python 環境が必要です。
https://github.com/danmar/cppcheck/tree/main/htmlreport
バージョンは 2.7 以上であれば大丈夫なようです。
また pygments に依存してるので pip install pygments もしておきましょう。

Cppcheck を実行

HTML レポートは cppcheck の結果 xml から作成するので、まずは cppcheck をかけて xml を出力します。

e.g.
cppcheck --enable=all --xml myproject 2> result.xml

Cppcheck 自体の使い方は(かなり昔に書いた記事ですが)こちら「ブログズミ: Cppcheck を使ってみた」、もしくは公式ドキュメントを参照してください。

HTML レポート

xml ができたらいよいよ html にします。

cppcheck-htmlreport --file=result.xml --title=iutest --report-dir=./html

--file で cppcheck で出力した xml を指定します。(複数指定可能)
その他のオプションは下記のヘルプを参考にしてください。

Usage: cppcheck-htmlreport [options]

Options:
  -h, --help            show this help message and exit
  --title=TITLE         The title of the project.
  --file=FILE           The cppcheck xml output file to read defects from. You
                        can combine results from several xml reports i.e. "--
                        file file1.xml --file file2.xml ..". Default is
                        reading from stdin.
  --report-dir=REPORT_DIR
                        The directory where the HTML report content is
                        written.
  --source-dir=SOURCE_DIR
                        Base directory where source code files can be found.
  --source-encoding=SOURCE_ENCODING
                        Encoding of source code.

結果

iutest の結果を gh-pages に入れておいたのでそちらを参考にしてみてください。
https://srz-zumix.github.io/iutest/test/cppcheck/



ソースコードも HTML ページ上で確認できます。

今回はこれで以上です。



2020年12月22日火曜日

[C++] Clang ではオーバーロードされた private 関数に明示的な実体化時のアクセスができない?

※この記事は C++ Advent Calendar 2020 22日目の記事です。

はじめに

過去に本ブログでも紹介した template の明示的実体化時に private メンバーアクセス可能な仕様を利用した private メンバー変数・関数へのアクセスですが、最近それを使っていて clang だけとある条件でアクセスできないことに気づきました。

この挙動が仕様として正しいのか正しくないのかは筆者ではわからないので、実挙動ベースの話になってしまいますことをご了承ください。

過去の記事

ブログズミ: [C++] Private な関数のテスト
ブログズミ: [C++] 本当に private なところ

サンプルコード

こちらは iutest の private メンバーのテストのための機能を使ったサンプルです。
Wandbox 用に圧縮したソースコードを使ってますので、実装を確認したい場合はこちらを御覧ください。
https://github.com/srz-zumix/iutest/blob/master/include/iutest_prod.hpp#L62

#define IUTEST_USE_MAIN
#include "iutest.hpp"

class A
{
public:
    int GetX(void) { return m_x; }
private:
    int m_x;
};

IUTEST_MAKE_PEEP(int A::*, A, m_x);

IUTEST(Peep, Test1)
{
    A a;
    IUTEST_PEEP_GET(a, A, m_x) = 42;
    IUTEST_EXPECT_EQ(42, a.GetX());
    IUTEST_EXPECT_EQ(42, IUTEST_PEEP_GET(a, A, m_x));
}

IUTEST(Peep, Test2)
{
    A a;
    IUTEST_PEEP(A, m_x) x(&a);
    x = 54;
    IUTEST_EXPECT_EQ(54, a.GetX());
    x += x;
    IUTEST_EXPECT_EQ(108, a.GetX());
    IUTEST_EXPECT_EQ(108, x);
}

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
https://wandbox.org/permlink/2ZPvpUz1zDe1KHHs

ポイントは IUTEST_MAKE_PEEP と IUTEST_PEEP_GET です。
IUTEST_MAKE_PEEP で private メンバーアクセスするための情報をセットアップし、IUTEST_PEEP_GET で実インスタンスの private メンバーへの R/W を実現しています。

問題のコード
class Hoge
{
    int x;
public:
    Hoge() : x(42) {}
private:
    int GetX() { return x; }
    
private:
    int gX() { return x; }
    int gX() const { return x; }
    int gX(int) { return x; }
};


IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, GetX);
IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, gX);

int main()
{
    Hoge hoge;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, GetX)() << std::endl;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, gX)() << std::endl;
}

Clang の場合はエラー
https://wandbox.org/permlink/roGkNKKwsnaLX7og 
GCC の場合は OK
https://wandbox.org/permlink/AWd5A19WWDznccfq

エラーとなるのは gX 関数の PEEP で、オーバーロードされた関数があるとダメなようです。
Visual Studio はバージョンによって static メンバー関数がダメだったりするのは認識してましたが、 clang でもうまくいかないケースがあることがわかりました。

この挙動に関してなにか進展があったら、追記したいと思います。

では。


2020年12月8日火曜日

Zapcc を使った複数プログラムの並列ビルドでハマった話

※この記事は C++ Advent Calendar 2020 8日目の記事です。

Zapcc とは

zapcc は clang ベースのキャッシュを利用した高速な C++ コンパイラーです。
zapcc はサーバープロセスのメモリ上にキャッシュを構築して高速化します。
ヘッダーファイルの解析結果や template のインスタンス化などがキャッシュされます。

プリコンパイルヘッダーを使うよりも生成されたコードもキャッシュされるので高速です。
類似のツールで ccache というキャッシュツールがありますが、こちらは翻訳単位ごとにキャッシュする仕組みなのでフルビルドのときはキャッシュ生成するだけでキャッシュの恩恵を受けられませんが、 zapcc の場合は同じヘッダーファイルを include してるファイルで、template インスタンス化などのキャッシュが利用されるためフルビルドでも高速になります。

また、zapcc サーバープロセスがいる間は別のプログラムのコンパイル時でもキャッシュ利用可能なので複数のプログラムをビルドする際も高速になります。

導入は簡単でビルド・インストール後、 CXX=zapcc++ とするだけで使えます。
自作の C++ テスティングフレームワーク iutest のテスト環境として zapcc インストール済みの Docker を用意してるので、よろしければそちらからでも試せます。
https://hub.docker.com/r/srzzumix/zapcc

ハマったこと

zapcc はビルドを高速に行うためにキャッシュをサーバーに蓄えます。
キャッシュはサーバープロセスが生きてるうちは有効です。
つまり、1つの実行ファイルをビルドするときだけでなく、その後に別プログラムをビルドする場合にもキャッシュが有効になります。
ライブラリの大量にあるテストプログラムをビルドするときには、このキャッシュがとても有効に働くと思います。

筆者が開発している iutest でも、複数のテストプログラムがあるのでビルド時間が短縮されるのを期待しましたが、結果は「テストの失敗」でした。

何が起きたか。

ビルドは特に問題なくできているように見えました、しかしながらテストは失敗している。
どうやらテストが失敗するのは、デフォルト設定ではなくテスト用に機能の有効化・無効化をしているテストでした。
iutest はコンフィグマクロを定義することで任意の機能を有効にしたり、無効にしたりするのですが、これが zapcc と相性最悪でした。。

どうやら、以下のようにとあるテストでコンフィグを変えても、キャッシュされたヘッダーファイルを利用してしまうため、#define が伝わっていないことがわかりました。

#define IUTEST_HAS_VARIADIC_TEMPLATES   0
#include "iutest.hpp"
  
対策

並列ビルドしているとキャッシュされたヘッダーを利用してしまうため、直列にしました。 -j4 とかせず -j1 を指定。
はい。もこの時点で Zapcc の恩恵を捨てています。いやむしろビルド時間的には悪化する場合も考えられます。。。

次に、キャッシュサーバーのプロセスが生きたままになっているので、1プログラム作る度に kill するようにしました。。。

Makefile はこんな感じになりました。

ifeq ($(CXX_NAME),zapcc++)
BUILD4ZAPCC=pkill zapcc++; sleep 1
endif

$(TARGETS1) : $(OUTDIR)/% : %.cpp $(IUTEST_HEADERS) $(MAKEFILE)
	$(BUILD4ZAPCC)
	$(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) -o $@ $< $(LDFLAGS)

なんか無理くりですが、 iutest はビルド速度改善を目的に zapcc を使っているわけじゃなく、zapcc コンパイラで不具合がないか検証するために使っているので、これでもまぁいいのです。。

最後に

zapcc はすごいけど万能ではなかった。



2020年12月1日火曜日

[C++] Concepts で外部ライブラリの template よりも優先されるオーバーロード関数を書く

※この記事は C++ Advent Calendar 2020 一日目の記事です。

はじめに

 C++20 で Concepts が導入されました。
コンセプト - cpprefjp C++日本語リファレンス

コンセプトはテンプレートパラメータを制約する機能で、「コンセプトによって関数オーバーロードやテンプレート特殊化」ができます。
今までテンプレート関数のオーバーロードを書く場合は SFINAE などのテクニックを使って書いていたと思いますが、コンセプトで書きやすくなりました。
これも大きな変化の1つですが、コンセプト関数が通常の関数よりも優先して lookup されるのも便利になった点の1つです。
コンセプトによるオーバーロードの場合、コンセプト関数が通常の関数よりも優先して lookup され、要件を満たすコンセプト関数がなかったら他の候補を探しに行きます。SFINAE では優先順位がつけられないケースでもコンセプトなら可能になりました。

どういうこと?
SFINAE では解決できなかった優先順位問題とコンセプトを使った実装の例

↑こちらは、std::cout << できない型の場合は "unknown" を出力するようにしようとしている様子です。

donot-change.h には std::cout するだけの template 関数 print があります。
こちらは変更ができない想定です。(外部ライブラリとか)

SFINAE.cpp では頑張って、 std::cout ができない場合で特殊化しオーバーロードしようとしてます。他の書き方を書いたりもしましたが、どうしても ambiguous になってしまって条件を満たすことができませんでした。

一方 Concepts.cpp は printable ではないコンセプト制約でオーバーロードするだけで実現できています。
すごく簡単ですね。

ちなみに
ちなみに donot-change.h を変更可能とした場合は、以下のように書くことができます。
namespace printer_internal
{
template<typename Elem, typename Traits, typename T>
::std::basic_ostream<Elem, Traits>& operator << (::std::basic_ostream<Elem, Traits>& os, const T&)
{
    return os << "unknown";
}
}

// 解決順序
// foo::operator <<
// ::operator <<
// ::printer_internal::operator <<
template<typename T>
void print(const T& val)
{
    using namespace ::printer_internal;
    ::std::cout << val << ::std::endl;
}
これは ADL の解決順序を利用して実現しています。
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/rlQoH37cvYTI23qo 
使い所は?
例でも示したとおり、オーバーロードしたい対象の関数を変更できるのであれば、そちらで解決する方法を模索するのが良いと思います。
ただ、外部ライブラリなど変更することができない場合、非侵入的に解決する方法として覚えておくと役に立つ日が来るかもしれません。

実例
そもそも私がなんで外部ライブラリの挙動をオーバーロードで変更したいと思ったのかというと、以下の理由でした。

* Google Test はアサーションが失敗すると、そのときの値を出力します
* std::cout できない場合はバイト列を出力します
* できない場合の対応は「ちなみに」の ADL を利用した方法で実現されています
* 古い Google Test ではこの機能がない
* 自作テスティングフレームワーク iutest は Google Test と互換性がある
* iutest は Google Test の拡張機能としての一面もある
* 古い Google Test と iutest の組み合わせでも不明な型を printable にしたい
* Google Test 側のコードは書き換えられない
* どうしよう

実際にコンセプトで対応してる部分はこちらになります。
最後に
教えていただいた いなむのみたま(@mitama_rs) 先生ありがとうございました。
ちなみにそのツイートにもぶら下がってますが、C++20 未満のコンパイラでこの問題を解決する方法も募集しておりますmm


2020年11月26日木曜日

[C++] -Weverything で得たもの


こちらで紹介した C++ 警告のまとめプロジェクトの作成にあたって、自作テスティングフレームワークの iutest で clang のすべての警告を有効にするオプション「-Weverything」を使って得た知見をまとめます。

-Wdouble-promotion

double 型テストしてたつもりが float になってたのに気づきました。

-Wextra-semi

なぜか二重についてた ; セミコロンに気づきました。

-Wnonportable-system-include-path

Windows 系のヘッダーが全部小文字だったのを修正しました。

-Wshadow-all

マクロ内で使っていた変数名が b とか info とかかぶりやすい名前だったのを修正しました。

-Wdocumentation-unknown-command

こちらはワークアラウンドの紹介になりますが、 Clang は Doxygen のコメントに対しての警告がありますが、対応していない Doxygen コマンドが存在します。

Diagnostic flags in Clang — Clang 12 documentation

その場合、コンパイルオプションに -fcomment-block-commands=private,internal,retval のようにコマンドを教えてあげることができます。
ただし、引数のない private や internal コマンドは別の -Wdocumentation 警告がでるようになってしまいます。

../include/internal/iutest_time.hpp:47:13: error: empty paragraph passed to '@internal' command [-Werror,-Wdocumentation]
 * @internal
   ~~~~~~~~~^

こちらの回避方法はまだ見つけてないので、見つけたら追記します。

以上。


2020年10月26日月曜日

[C++][IWYU] Include What You Use CL を VS2019 対応しました

include-what-you-use-cl を VS2017/VS2019 に対応しました。
include-what-you-use-ci (以下 IWYU-CL) は include-what-you-use (以下 IWYU) を Visual Studio のプラットフォームツールセットとして選択できるようにするツールです。
プラットフォームツールセットとすることでプロジェクトの設定(インクルードパスなど)をそのまま利用して IWYU をかけることを目的に作りました。
VS2017 から VS{version}COMNTOOLS 環境変数がなくなったりと、インクルード関連の構成が一新されてから更新が滞ってましたが、最近 vswhere の存在を知り更新することにしました。

あと同僚に突っ込まれたので README も更新して、使い方を書きました。

Include-What-You-Use-CL

Include-What-You-Use-CL is Visual Studio toolset for Include-What-You-Use

Dependency

Include-What-You-Use

Install

git clone https://github.com/srz-zumix/include-what-you-use-cl.git
cd include-what-you-use-cl
install.bat

Usage

  1. Project Settings > Platform toolset
    Select "Include-What-You-Use" toolset
  2. Compile
  3. Get Include-What-You-Use result
    output

Uninstall

uninstall.bat

IWYU は cpplint にも組み込まれてたりするようなので、わざわざ cl から呼ぶ必要性はない気もしますが。。
お手軽に試せるので IWYU-CL も試してみてくださいmm

今回は以上です。
では。

2020年10月21日水曜日

lizard で C++ コードメトリクス

今の会社に来てから OS が Windows とは限らない。むしろ macOS が多くなったので CCCC の代わりに lizard を使ってみました。

インストール
pip install lizard
で終わりです。
使い方
ヘルプ見たらだいたい分かると思いますが、パス指定したら解析してくれます。
-l で言語指定ができます。(e.g. -l cpp)

--xml で cppncss xml 形式で print されるのでファイルに出力したら Jenkins でも簡単に可視化できます。

--html で HTML レポート出力もできるのでさっと確認したい人はこれで見ると良いでしょう。
iutest の結果
lizard 入りの Docker image 作って GitHub Actions でレポートを取ってみました。
作成したイメージはこちらです。 https://hub.docker.com/r/srzzumix/lizard

GitHub Actions の YAML は以下のようになります。
lizard で出力した HTML レポートを成果物として保存しています。
  lizard:
    runs-on: ubuntu-18.04
    needs: prepare
    steps:
    - uses: actions/checkout@master
    - name: Lizard
      uses: docker://srzzumix/lizard
      with:
        args: -o lizard.html --html ./include
    - name: Archive code metrics results
      uses: actions/upload-artifact@v1
      with:
        name: lizard.html
        path: lizard.html

実行結果はこのようになります。

成果物から HTML レポートをダウンロード可能です。



最後に
今回はメトリクスを集計するところまでをやりました。
xml を取得して閾値チェックなどできると良いかもしれません。
取得したメトリクスを利用する事例ができたら、また記事にしたいと思います。

今回は以上。では。

2020年9月25日金曜日

[C++] 警告のコンパイラー対応表を作り始めました

 srz-zumix/awesome-cpp-warning: c++ warning correspondence table (Clang/GCC and Visual Studio)

マルチプラットフォームやってると、Visual Studio (VC++) と clang で警告の制御方法が異なるので面倒くさいなーって思っていたので対応表を作りました。
(全部 clang にしたら楽なんですけどね・・・)



特に vc++ は C4096 とかの ID でコントロールするのでわかりにくいんですよね。
あとは当然、clang では警告になるけど、vc++ は警告ないとか。逆パターンとか、clang だとエラーとか、あるあるだと思います。
そんなマルチプラットフォーム開発のビルドエンジニア向けにまとめた(まとめている)ものが↑↑です。

とりあえず、VC++ の警告を一通りみてサンプルコードがあるものや、すぐに再現できたものに対してはこちらの表に記載してます。
https://github.com/srz-zumix/awesome-cpp-warning/blob/master/VCLIST.md



そして、おそらくみんなが欲しいのは clang/gcc の -Whogehoge 警告が vc++ だと ID いくつなのかって点だと思うので top にまとめてます。
(すべての警告を無視(よくないけど)したり、すべての警告を as error として直さなければならない環境ならあまり必要ないかも?)


今後も対応表を増やしていこうと思ってます。
もちろん PR 大歓迎です!!

今回は以上。では。

2020年7月15日水曜日

[Travis CI] Segmentation fault したときにスタックトレースを出力する設定

テストがクラッシュして失敗したときの調査が手間だなーということで対応しました。

対応したときの PR がこちらです。
差分で見ると、なにを追加したか見やすいと思います。
[Travis CI] core dump by srz-zumix · Pull Request #288 · srz-zumix/iutest

以下、ポイントを説明していきます。

導入

gdb のインストール


コアダンプファイルの出力設定


まず、コアダンプファイルが出力されるように ulimit の設定をします。
また、iutest ではテスト時に複数の実行ファイルを実行するため、コアダンプファイル名に実行ファイルの名前もつけるようにしています。
(コアダンプファイルの中身から取れる気もするけど、これで十分)

クラッシュしたらスタックトレースを出力する


実行ファイルの名前解決
linux - Core dump file name truncated - Stack Overflow
%e だと 15 文字で truncate されてしまい、実行ファイル名が正しく取れなかったので以下のような対応をしました。
gdb で coredump 開くと実行ファイルがなんだったのか出力されるので、それを取得してます。


      for f in `find . -maxdepth 1 -name "core_x_*"`; do
        COREFILE=${f}
        EXECFILE=${f##*/core_x_}
        if [ ! -f "${EXECFILE}" ]; then
          EXECFILE=`gdb -c "${COREFILE}" -batch | grep -o -e "\./[A-Za-z_]*"`
        fi
        gdb -c "${COREFILE}" ${EXECFILE} -ex "thread apply all bt" -ex "set pagination 0" -batch
      done


出力例




最後に
最近はローカル環境で実行確認することも減ってきたので CI 上でデバッグできるようにしておくのは便利でいいですね。

今回は以上です。
では。

2020年7月5日日曜日

[CI][CodeReview] LGTM.com 始めました

LGTM.com ってのがあるのを知ったので使ってみました。


サインアップ~解析まで
サインアップから解析するまで一気に説明します。 まずはトップページの右上からログインします。 GitHub や BitBucket などのアカウントを使ってサインアップ可能になっています。
 
次に LGTM の GitHub App をインストールします。
リポジトリ選択では、解析したいリポジトリを選択、または全部許可にします。

LGTM.com に戻ると解析始まってると思います。

今回試したのは「自作 C++ テスティングフレームワーク」の iutest です。
C/C++ の場合はコードのビルドも必要なようですが、勝手に CMake のファイルを見つけて解析してくれました。



↓こちらが解析結果
他のレビュー系サービスや lint を使ってはいたのですが、案外問題がありました。

PR の解析
PR の解析はプロジェクトの↓が「Automated PR code reviews enabled」になっていると有効になっています。
無効になっている場合はボタンを押して有効にしましょう。

この状態で PR でレビュー箇所を修正したりするとコメントが付きます。

詳細はコメントのリンクもしくは、プロジェクトのところにある「Automated PR code reviews enabled」または、「Integrations」タブをクリックすると開きます。


メインブランチの解析
いろいろ問題が明るみになって早速修正、PR 上で修正確認できたのですが、マージ後の master ブランチの解析結果が変わらず、どうやったら解析されるのかなーと調べてたら、ドキュメントにちゃんと書いてありました。


LGTM.com は1日1回くらいの周期で新しいコミットを確認して解析するそうです。
なので、修正されるかどうかは PR で確認して、マージしたら気長に待つしかなさそうです。
チェック項目の抑制

LGTM.com で C/C++ のチェック項目はデフォルトで 140 あります。
iutest でいくつか抑制したい項目があったので方法書いておきます。

冒頭のツイート先の記事でも書かれていますが
(git push してすぐ lgtm に反映されるわけではない(数時間から半日くらいかかる)ので, 動作確認が手探りになってしまい時間がかかる)

lgtm.yml をコミットしてもすぐには反映されないみたいです。
ちょっとトライ&エラーが難しそうですが、
とりあえず、ドキュメント通りに書いておけば大丈夫なはず!

YAML で設定
YAML で ID ごとに exclude/include 指定ができます。
また、severity/tags でまとめて除外することもできるようです。
コメントで設定
C++ の場合は、「// lgtm[id]」を問題の行末に書きます。

Configuration のテスト
設定は web 上からテストすることも可能です。
Logs の右上に「Test analysis configuration」ボタンがあるので、そこを開くと任意のコンフィグを記述して解析を実行できます。
lgtm.yml をコミットしても即座に適用されないようなので、config はこちらを使ってテストすると良さそうです。



最後に
LGTM.com は CodeQL を使って解析をしているので、今まで使ってきた lint ツールなどとはまた違った解析結果が得られました。
こういった静的解析ツールは、手法の異なるいくつかのツールを併用したほうがより多くのインプットを得られるので、CodeQL ベースの解析の導入がまだであれば導入をオススメします。
また、本記事では触れませんでしたが、クエリは独自に書くことも可能です。
プロダクト固有のドメインをチェックしたりとかできそうです。

また、冒頭のツイートのリンク先でも記述されていますが、CodeQL の会社(Semmle)が GitHub に買収されていますので、今後は GitHub の機能とかでより使いやすくなったり、クエリが増えていくかもしれません。


今回は以上です。
では。



2020年6月29日月曜日

Wandbox の CLI ツールを作ってみた


タイトルの通りコマンドラインツールを作ってみました。
リポジトリはこちら。https://github.com/srz-zumix/wandbox-api/

言語は Python で PyPI に Publish してますので、 pip install wandbox-api ですぐに使えます!
PyPI に初めて Publish しました〜
この辺は「Github ActionsでPyPIにパッケージを公開する」を参考に、GitHub Actions で tag をトリガーに Publish されるようにしました。
name: PyPI Publish
on:
  push:
    tags:
      - v*

jobs:
  pypi:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@master
    - name: Set up Python 3.7
      uses: actions/setup-python@v1
      with:
        python-version: 3.7
    - name: Init .pypirc
      env:
        PYPI_USERNAME: __token__
        PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
      run: |
        echo -e '[pypi]' >> ~/.pypirc
        echo -e "username = ${PYPI_USERNAME}" >> ~/.pypirc
        echo -e "password = ${PYPI_PASSWORD}" >> ~/.pypirc
    - name: Publish
      run: |
        pip install twine wheel
        python setup.py sdist bdist_wheel
        twine upload --repository pypi dist/*


現在の機能は、Wandbox が対応している言語・コンパイラー・オプションのリストアップとコンパイル&実行です。また、C++ 用に特化した wandbox-cxx コマンドもあります。
使用例
言語リストを取得
$ wandbox lang
Bash script
C
C#
C++
CMake
CPP
CoffeeScript
Crystal
D
Elixir
Erlang
F#
Go
Groovy
Haskell
Java
JavaScript
Lazy K
Lisp
Lua
Nim
OCaml
OpenSSL
PHP
Pascal
Perl
Pony
Python
R
Rill
Ruby
Rust
SQL
Scala
Swift
TypeScript
Vim script
コンパイラーのリストを取得
-l オプションで言語を選択してリストアップします。言語指定がない場合はすべての言語のコンパイラーをリストアップします。
$ wandbox -l C++ compiler
gcc-head
gcc-9.3.0
gcc-9.2.0
gcc-9.1.0
gcc-8.3.0
gcc-8.2.0
gcc-8.1.0
gcc-7.3.0
gcc-7.2.0
gcc-7.1.0
gcc-6.3.0
gcc-6.2.0
gcc-6.1.0
gcc-5.5.0
gcc-5.4.0
gcc-5.3.0
gcc-5.2.0
gcc-5.1.0
gcc-4.9.3
gcc-4.9.2
gcc-4.9.1
gcc-4.9.0
gcc-4.8.5
gcc-4.8.4
gcc-4.8.3
gcc-4.8.2
gcc-4.8.1
gcc-4.7.4
gcc-4.7.3
gcc-4.6.4
gcc-4.5.4
gcc-4.4.7
clang-head
clang-10.0.0
clang-9.0.0
clang-8.0.0
clang-7.0.0
clang-6.0.1
clang-6.0.0
clang-5.0.0
clang-4.0.1
clang-4.0.0
clang-3.9.1
clang-3.8.1
clang-3.7.1
clang-3.6.0
clang-3.5.0
clang-3.4
clang-3.3
clang-3.2
clang-3.1
zapcc-2017.08
zapcc-1.0.1
コンパイラーのオプションを取得
-c オプションでコンパイラーを選択すると、そのコンパイラーで使用できるオプションをリストアップします。指定がない場合はすべてのオプションをリストアップします。

$ wandbox -c clang-head option
C++: 
warning (default)
optimize
cpp-verbose
boost-1.73.0-clang-head (default)
  boost-nothing-clang-head
  boost-1.60.0-clang-head
  boost-1.61.0-clang-head
  boost-1.62.0-clang-head
  boost-1.63.0-clang-head
  boost-1.64.0-clang-head
  boost-1.65.0-clang-head
  boost-1.65.1-clang-head
  boost-1.66.0-clang-head
  boost-1.67.0-clang-head
  boost-1.68.0-clang-head
  boost-1.69.0-clang-head
  boost-1.70.0-clang-head
  boost-1.71.0-clang-head
  boost-1.72.0-clang-head
  boost-1.73.0-clang-head
sprout
msgpack
gnu++2a (default)
  std-c++-default
  c++98
  gnu++98
  c++11
  gnu++11
  c++14
  gnu++14
  c++17
  gnu++17
  c++2a
  gnu++2a
cpp-no-pedantic (default)
  cpp-no-pedantic
  cpp-pedantic
  cpp-pedantic-errors
C++ のコードをビルド・実行する
wandbox-api パッケージには C++ 用のコマンドとして、wandbox-cxx と wandbox-g++/wandbox-clang++ が含まれています。
cxx は wandbox コマンドに -l C++ を指定したのと同等です。wandbox-g++/wandbox-clang++ はさらに -c オプションでコンパイラーの指定をしたものになります
(バージョンはそれぞれ head)
また、これらは通常の wandbox コマンドのコマンドラインオプションに加えて、 C++ コンパイラー向けの Wandbox オプションがコマンドラインオプションで設定できるようになっています。
  --std VERSION         set --std options
  --boost VERSION       set boost options version X.XX or nothing
  --optimize            use optimization
  --cpp-verbose         use cpp-verbose
  --sprout              use sprout
  --msgpack             use msgpack
run に続く引数は、コンパイラーへの引数としてそのまま渡されます。
$ wandbox-clang++ run main.cpp test.cpp
program_message:
Hello, Wandbox!
test
$ wandbox-clang++ run main.cpp test.cpp -DTEST
program_message:
test
test
-s オプションを付けると permlink を発行できます。
wandbox-clang++ -s run main.cpp test.cpp -DTEST
program_message:
test
test


permlink: TuvMXWckFrkxGPAs
url: https://wandbox.org/permlink/TuvMXWckFrkxGPAs
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/6AGrKCojBOo1oCUv


使用したソースコードはこちらです。
今後
今後、ちまちまと他の言語のコマンドも追加していこうと思います。
もちろん PR 大歓迎です!
今回は以上です。では。



2020年4月30日木曜日

[C++] -ftime-trace オプションと Chrome でビルド時間の可視化

C++ のビルド速くしたいなーと思ってて、そのためにはまずは計測だよねってことで調べてたら行き着いたのですが、clang に -ftime-trace があり、その出力を Chrome で可視化ができるとのこと! (懐かしき SN Systems..)

早速、仕事でも個人でも使ってみたんですが、これはとても便利ですね。




しかも、 「chrome://tracing」 はフォーマットが公開されているので、これに従って出力すれば他にも可視化できそうです。
Trace Event Format - Google ドキュメント
↓は CircleCI での並列具合を可視化したもの。こちらについては来週ブログにしたいと思います。

今回は以上です。では。


2019年12月6日金曜日

[C++] 本当に private なところ

※ この記事は「C++ Advent Calendar 2019」6日目の投稿です。


private メンバー変数の R/W テスト
まずはこちらをご覧ください。
#include "iutest.hpp"
//origin>> #include "../../include/iutest.hpp"
#include <iostream>

int main(int argc, char** argv)
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}

class Test
{
private:
    int A:12;
    int B:4;
    int C:4;
    int D:12;
    int E;
public:
    Test()
        : A(0x777)
        , B(0x3)
        , C(0x4)
        , D(0x400)
        , E(1)
    {}
};

IUTEST_MAKE_PEEP(int Test::*, Test, E);

IUTEST(PeepTest, MemberVariable)
{
    ::Test test;
    IUTEST_EXPECT_EQ(1, IUTEST_PEEP_GET(test, ::Test, E));
    IUTEST_PEEP_GET(test, ::Test, E) = 4;
    IUTEST_EXPECT_EQ(4, IUTEST_PEEP_GET(test, ::Test, E));
}
https://wandbox.org/permlink/GqDQ4zeCrzv1HABq

private メンバーである Test::E への書き込み・読み込みができていることがわかると思います。

private メンバー変数(ビットフィールド)の R/W テスト
続いて、上でアクセスしている private 変数を E から A に変えてみます。

IUTEST_MAKE_PEEP(int Test::*, Test, A);

IUTEST(PeepTest, MemberVariable)
{
    ::Test test;
    IUTEST_EXPECT_EQ(1, IUTEST_PEEP_GET(test, ::Test, A));
    IUTEST_PEEP_GET(test, ::Test, A) = 4;
    IUTEST_EXPECT_EQ(4, IUTEST_PEEP_GET(test, ::Test, A));
}
https://wandbox.org/permlink/NRPvHweGaDp6HAdy

今度はコンパイルエラーです。

解説
プライベートにアクセスした方法
上のコードで利用したテスティングフレームワークは iutest です。
private メンバーへのアクセスはこのフレームワークの PEEP 機能を利用しています。
PEEP は template explicit instantiation で private にアクセス可能なことを利用して、private メンバーのアドレスを取得して実現しております。
詳しくは昔書いたこちらの記事を参考にしてください。(「ブログズミ: [C++] Private な関数のテスト」)

ビットフィールドにアクセスできなかった理由
error: address of bit-field requested
上記 PEEP の方法ではアドレスを取得できる必要があるため、
アドレスが取れないビットフィールドではアクセスできないわけです。
(言語法律家によるアクセスが可能な場合はビットフィールドでもアクセスできますが・・ : https://wandbox.org/permlink/zYC1hAYuqqixaEUn

まとめ
C++ にプライベートはあった

2019年7月24日水曜日

[Wandbox] 処理速度比較したいときのテンプレ

C++ 書いてる(じゃないな見てる)と、これはこう書いたほうが速いんじゃないか、こう書いたほうが簡潔になるけどパフォーマンス落ちないかな、と思うことが多々あります。
そんなときは、サクッと Wandbox で試してみるのですが毎回計測コードをどう書くんだっけ?となっていたのでテンプレを用意しました。





2019年7月16日火曜日

[Visual Studio] ステップフィルターのカスタマイズでデバッグを楽にする

かなり前に Visualizer を紹介しましたが、今回はステップフィルターの紹介をします。
ブログズミ: [Visual Studio] デバッガー変数表示のカスタマイズ

Visual Studio ではステップインする際に、
特定の関数には入っていかないようにする設定がユーザー定義でできるようになっています。
Customize C++ stepping behavior independent of Just My Code settings

それを設定して何が便利なのか?
よくある事例で見てみましょう。

まずは設定なし。

そして、設定あり。


どちらも UnitTestSource::GetInstance().Initialize(); の Initialize にステップインしようとしている様子です。
いかがでしょう?
前者のように GetInstance にいちいちステップインしちゃうのが煩わしく感じてる人は多いのではないでしょうか?

ステップフィルターを設定した後者は GetInstance() の中に入っていかなかったですね。
このように、1行に複数の関数呼び出しがある場合に、興味がない関数へのステップインをしないようにするとデバッグがしやすくなると思います。

今回紹介する .natstepfilter を使って、この煩わしさから開放されましょう!


設定の仕方
.natstepfilter 拡張子のファイルを作成し、
「%VsInstallDirectory%\Common7\Packages\Debugger\Visualizers」もしくは「%USERPROFILE%\My Documents\\Visualizers」に保存するだけです。

ファイルのフォーマットは xml になっています。
この xml で関数の指定とその関数に対して、ステップインするか、しないかの設定を行います。
以下は GetInstance にステップインしないようにする .natstepfilter の例です。

<Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>

.natstepfilter は複数のファイルに分けて書くことができますので、stl.natstepfiler と iutest.natstepfilter のように namespace や用途に合わせて分けておくと便利だと思います。



iutest の例
さて、上記で iutest での GetInstance の事例を紹介しましたが、
iutest では、テスティングフレームワークの利用者はフレームワークの内部実装には興味がなく、テストコードにのみ興味があるはずという考えのもと、テストコードから内部実装にステップインしないようにした natstepfilter を提供しています。

<?xml version="1.0" encoding="utf-8"?>  
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">  
    <Function>
        <Name>iutest::TestEnv::environments</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestSource::Run</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionSuccess</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionFailure</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionResult.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionHelper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertPred.*Helper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::PrintToString.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::WithParamInterface.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::Test::RecordProperty.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestImpl::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::detail::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iuutil::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::matchers.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::internal::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>std::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
</StepFilter>

ユーザーが集中したいコードにのみ、ステップインするのでテストコードのデバッグがしやすくなったのではないか、と思ってます。

Resharper C++ をインストールしていると利用できない
https://pleiades.io/help/resharper/Reference_Options_Tools_Debugger_CPP.html
Resharper C++ にステップフィルターの機能があるため、すべてそちらの管理になります。
そのため、.natstepfilter の設定は引き継がれません。(継承かインポートできると嬉しいですが・・・)

Resharper 使っている方はご注意くださいmm


最後に
Visual Studio は "知っていれば" 便利な機能が結構あります。
ツールは使ってなんぼ。ただ使ってるだけじゃもったいないです。

これまでもいくつか機能を紹介してきましたが、今後も Visual Studio にはお世話になると思うので、また便利な機能を知ったら紹介したいと思います。

では。