Clang with Microsoft CodeGenがでたので試す

# C++初心者Advent Calendar 2015
この記事は[C++初心者Advent Calendar 2015](http://www.adventar.org/calendars/922) 9日目の記事です
[<< 8日目 | C++のポインタ渡しと参照渡しの使い分け](http://cocodrips.hateblo.jp/entry/2015/12/08/221722) || [10日目 | テンプレートでコケた話 >>](http://qiita.com/Roadagain/items/8ec4ab4ba6c46fe0ce41)
[17日目 | C99からC++14を駆け抜けるC++講座 >>](http://qiita.com/yumetodo/items/e49a673afd9a3ecb81a8)

個人的には、[歌舞伎座.tech #8 「C++初心者会」](https://ezoeryou.github.io/blog/article/2015-05-18-kabukiza-tech-8.html)とか見て以降、「初心者」が怖くなってしまっていますが([初心者がBoost.asioをつかえるもんか！](http://www.shigemk2.com/entry/kbkz_tech.8.3))、ここまでは初心者向けで**ものすごくホッとしています**。初日の
[初心者が C++ を勉強するときに最低限押さえておいたほうがよい C++11/14 の機能](http://secret-garden.hatenablog.com/entry/2015/12/01/204727)
を除いてですが(最近の初心者は継承が使えるのか・・・怖い)

[8日目 | C++のポインタ渡しと参照渡しの使い分け](http://cocodrips.hateblo.jp/entry/2015/12/08/221722)とかはさっぱりしていてわかりやすいのではないでしょうか。**なので見ろ(ぇ)**。

以下、4日目の[C++を始めよう for windows - Qiita](http://qiita.com/cpp_maid_BOT/items/13eab3a134e3f6794f07)を見ている前提で話が進みます。**見てない方は先にどうぞ**。

# 追記

現在、Clang with Microsoft CodeGenのclangのバージョンが3.8のままな気がします。最新のclangのほうが絶対良いと思われるので、 @kazatsuyu さんの`fafnir`というツールを使うことをおすすめします。詳細は

- [Visual Studioでも最新のClangが使いたい！](https://qiita.com/kazatsuyu/items/b85e97e38a25bc302054)
- [kazatsuyu/fafnir: Clang MSBuild toolset for Visual Studio 2017](https://github.com/kazatsuyu/fafnir/)

# はじめに

先日Clang with Microsoft CodeGenなるものが出た。なのでこれはなにかという話と、そもそもコンパイラって？というお話から書いていこうと思います。

で、MSの名前が出た時点で察しですが、for Windowsな記事となっています。え？Linux？Mac?おめーら、優秀なコンパイラあんだろーが。

# 目的

- Clangの存在を世に広める
- 最近はMSも頑張ってることを伝える
- おのれMS

・・・いやですね、
[C++を始めよう for windows | Qiita](http://qiita.com/cpp_maid_BOT/items/13eab3a134e3f6794f07)
で、Visual Studioの紹介自体はあったので。これは書かねばなるまいということで。
だって、gccの扱いが

>gccはLinux等でよく使われるコンパイラですが、今は忘れてもかまいません。

でclangに至っては記述なしですからね、これは宣伝せざるを得ません(謎の使命感)

# コンパイラとは

コンパイラとは特定言語で書かれたコードを機械言語、ないしもとより下位の言語(中間言語)に翻訳するものです。
有名なコンパイラとしては

- gcc/g++
- clang/clang++
- Visual Studio付属のcl.exe
- icc

などでしょうか。(bcc32.exeなんてなかった)

この後話すClang with Microsoft CodeGenとは細かい話を抜けば、Visual StudioをIDEとしてつかいつつ、コンパイラだけClangに差し替える、というものです。

# Clang(クラン)とは

もともと、iPhoneで有名なAppleがLLVMという中間言語を経由してC/C++のコードをコンパイルするプロジェクトを立ち上げたものです。gccとちがいマルチスレッドで**動作も高速**、LLVMを使うことによりgccより最適化がし易いなどなどの特徴があります。なおgccがGPLv３というライセンスなのに対し、ClangはUniversity of Illinois/NCSA Open Source Licenseというライセンスで、コピーレフト絶対主義者の自由ソフトウェア主義者からは妬まれています。パルパル。

- [Clang - Wikipedia](https://ja.wikipedia.org/wiki/Clang)
- [LLVM Clang の Windows へのインストールと使い方 | プログラマーズ雑記帳](http://yohshiy.blog.fc2.com/blog-entry-294.html)
- [LLVM/Clangがぜってーサポートしねーと宣言しているLinuxカーネルに多用されているGCC拡張 | 本の虫](http://cpplover.blogspot.jp/2013/04/llvmclanglinuxgcc.html)

C++に関しては、後発のコンパイラにもかかわらず、**もっともC++規格準拠がはやい**コンパイラとなっています。まあ細かいバグはあるんですが。

# これまでのWindowsでClangを利用する方法

## msys2 mingw clangをつかう

多分これが一番はやいと思います。**今でも。**

1. 7-Zipを落とす  
https://sevenzip.osdn.jp/  
より64bit版もしくは32bit版を  
既に入っている人も、2015/11/19に随分久しぶりに最新版が出たのでバージョンを上げるといいです
2. 7zipをインストール  
ダブルクリックして実行すればいいです。
3. msys2を落とす  
4. 
http://sourceforge.net/projects/msys2/files/Base/  
よりお使いのアーキテクチャ(おそらくはx86_64)をクリックしmsys2-base-[アーキテクチャ]-[日付].tar.xz
を。exeの方は１回も使ったこと無いのでわかりません。
4. 7-zipで解凍
5. ``msys2_shell.cmd``をダブルクリック、``Close Window``と言われたらばってんを押して閉じる
6. 再び``msys2_shell.cmd``をダブルクリック、``pacman -Syuu``と打ち実行、また閉じる
7. 再び``msys2_shell.cmd``をダブルクリック、``pacman -S mingw-w64-i686-clang mingw-w64-x86_64-clang``とと打ち実行、また閉じる
8. ~~コマンドプロンプトで`msys2_shell.cmd`のあるパスに移動し、`call msys2_shell.cmd -mingw64`(64bit向けのコンパイル)または`call msys2_shell.cmd -mingw32`(32bit向けのコンパイル)を実行~~`mingw64`(64bit向けのコンパイル)または`mingw32.exe`(32bit向けのコンパイル)を実行
9. clangコマンドが使える！

## mingwを自力で入れてさらにclangを入れる

Cドライブ直下にmingwを置かないといけなくて、シンボリックリンクではダメだったので私はやっていません

## Visual Studioを導入してからClangを入れる

VSが入っている状態で
http://llvm.org/releases/download.html
Clangを入れるとVisual StudioからもClang-clが使えるようになる



# Clang with Microsoft CodeGen

- [Clang with Microsoft CodeGen(clang 3.7)(preview 1)](http://blogs.msdn.com/b/vcblog/archive/2015/12/04/introducing-clang-with-microsoft-codegen-in-vs-2015-update-1.aspx)
- [Clang with Microsoft CodeGen(clang 3.7)(January 2016)](https://blogs.msdn.microsoft.com/vcblog/2016/01/20/clang-with-microsoft-codegen-january-2016-released/)
- Clang with Microsoft CodeGen(clang 3.7)(February 2016)(Update2 previewにあったぽい？)
- [Clang with Microsoft CodeGen(clang 3.7)(March 2016)](https://blogs.msdn.microsoft.com/vcblog/2016/03/31/clang-with-microsoft-codegen-march-2016-released/)
- [Clang with Microsoft CodeGen(clang 3.8)(May 2016)](https://blogs.msdn.microsoft.com/vcblog/2016/06/03/clang-3-8-in-the-may-release-of-clang-with-microsoft-codegen/)
- Clang with Microsoft CodeGen(clang 3.8)(July 2016)

## なぜClang with Microsoft CodeGenか
こうした方法があったわけですがどれもいまいちでした。最初のmsys2を使うものは、ついでにgccも入って便利ではあるんですが、コンパイルはコマンドラインなので、makefileを書かねばならず、**んなもん初心者に書けるか**、というお話です。かと言ってVSをいれてからClangを入れる方法ははっきり言って**実験段階**というか、VSとの連携が不十分でした
そして、**最大のメリットは、Visual Studioの唯一の利点、優秀なデバッグ機能がフルに使える**ということです。あのデバッグ機能がなければ、誰ひとりとしてあんな糞コンパイラ使ってないでしょう。

## Clang with Microsoft CodeGenの仕組み
ではこのClang with Microsoft CodeGenはどのようにコンパイルがなされるのでしょうか。

| コンパイラ名                 | flow                                                     |
|------------------------------|----------------------------------------------------------|
| mingw clang                  | ソースコード→LLVM IR→実行ファイル                  |
| VS default                   | ソースコード→MS独自の中間言語→実行ファイル               |
| Clang with Microsoft CodeGen | ソースコード→LLVM IR→MS独自の中間言語→実行ファイル |

こんな感じです。(だれか図をください)
なお

>Visual StudioにClangフロントエンドがやってくる
>http://cpplover.blogspot.jp/2015/10/visual-studioclang.html
>MS独自のプロプライエタリなTwo-phase lookupすらまともにできない規格違反のクソC++コンパイラーの開発も続行されるらしい。

某友人はこれを聞いて思わずFワードを吐いていました。大丈夫だ、気持ちはわかる。

## 以下の内容を動画化した

ぶっちゃけわかりにくいので、**動画にしました**。
[【ゆっくり実況】Clang with Microsoft CodeGenの導入実況 - ニコニコ動画:GINZA](http://www.nicovideo.jp/watch/sm27746850)
どうぞ御覧ください。(宣伝乙とか言わない)

## じゃあ導入するか

1. https://www.visualstudio.com/ja-jp/downloads/download-visual-studio-vs.aspx
に行き、
![ダウンロード  Visual Studio.png](https://qiita-image-store.s3.amazonaws.com/0/94177/7cc6d1de-3a09-b7d5-5ed4-8209007eb39f.png)  
ダウンロードする  
そして実行する  
カスタムインストールか否かが出たらカスタムインストールに。
2. 選択画面が出たら  
``クロスプラットフォームモバイル開発``→``Visual C++モバイル開発``→``Clang with Microsoft CodeGen(2016年1月)``にチェックをつける  
``プログラミング言語``→``Visual C++``にチェックが付いているか確認する
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/94177/523b8224-a8f8-280b-f5b6-8cb6ae0ec473.png)


3. インストール。気長に待つ

## どうやって使うか

新しいプロジェクト→インストール済み→Visual C++→クロスプラットフォーム
にstatic/dynamic libraryをClangで作れるものがありますが、そんなもの初心者はお世話にならないので

>http://qiita.com/cpp_maid_BOT/items/13eab3a134e3f6794f07
>「新しいプロジェクト ＞ Visual C++ > Win32コンソールアプリケーション」で名前を適当に
アプリケーションの種類を「コンソールアプリケーション」追加のオプションを「空のプロジェクト」にチェックを入れ完了します
そして「ソリューションエクスプローラーからソースファイルを選び右クリック ＞ 追加 ＞ 新しい項目 ＞ C++ファイル名前mainで追加」

でいいです(ちなみに[Ctrl]+[Shift]+[A]なんて便利なショートカットもあるんやで。)

**ここからが大事です**

1. プロジェクト→xxxのプロパティ→構成マネージャを開く
2. アクティブソリューション構成→新規作成で、**設定のコピー元が空の状態で**適当な名前をつけて構成を作成します。私は``clang_Debug``と``clang_Release``の2つを追加しています。
3. 構成マネージャを閉じます
4. そのままプロパティページが開いていると思うので、プラットフォームを~~x64~~すべてのプラットフォームに、構成→複数の構成で先ほど作った構成のみチェックをつけます
5. 構成プロパティ→全般  
にある  
**プラットフォームツールセット**  
を  
~~Clang 3.7 with Microsoft CodeGen (v140_clang_3_7)~~  
Visual Studio 2015 - Clang with Microsoft CodeGen (v140_clang_c2)  
にします
6. ~~構成プロパティ→C/C++→コード生成→C++の例外を有効にする を「はい」に。(テーブルをアンウィンドってなんだ)~~Clang with Microsoft CodeGen (January 2016) でデフォルトで有効になりましたね
7. **構成プロパティ→C/C++→全般→デバッグ情報の形式で``完全なデバッグ情報 (DWARF2) (-g2 -gdwarf-2)``を選択**

あとはコード書くだけです。

コードは
http://faithandbrave.hateblo.jp/entry/20131119/1384837618
より。

```cpp:C++14_constexpr
constexpr void square(int& x)
{
    x *= x;
}

constexpr int f(int x)
{
    square(x);
    return x;
}
```

こんなコードももちろん動きます。あとは
https://gist.github.com/yumetodo/dad352ffdc27c19cf825
こんなコードとか。

## 注意

### IntelliSense

**IntelliSenseは対応していません**。いっその事IntelliSenseを切ってもいいかもしれません。

### Windows.hについて

**追記:いつの間にやら修正されました。**

~~多分7月版からだと思うんだけど、Windows.hをincludeすると~~

```
Windows Kits\8.1\Include\um\combaseapi.h(229,21): error : unknown type name 'IUnknown'
static_cast<IUnknown*>(*pp);    // make sure everyone derives from IUnknown
```

~~とか怒られるようになりました。というわけで使うときは~~

```cpp
#if !defined(CINTERFACE) && defined(__c2__) &&  __clang_major__ == 3 && __clang_minor__ == 8
//To avoid compile error
//C:\Program Files (x86)\Windows Kits\8.1\Include\um\combaseapi.h(229,21): error : unknown type name 'IUnknown'
//          static_cast<IUnknown*>(*pp);    // make sure everyone derives from IUnknown
struct IUnknown;
#endif
#include <Windows.h>
```

~~としましょう。~~

詳細
Clang with Microsoft CodeGen(2016/07版)でWindows.hを使うときに注意すべきこと
http://qiita.com/yumetodo/items/a8c408078766a5c81e31

### asm

>https://blogs.msdn.microsoft.com/vcblog/2015/12/04/clang-with-microsoft-codegen-in-vs-2015-update-1/#known-issues-in-the-first-preview
>No inline asm on any architecture. You will get a diagnostic that says “Inline assembly is not supported” or “GNU-style inline assembly is disabled”

~~アセンブリ使えません。全滅です。SIMDとかは試してないけど手動ではできないんじゃね？今後に期待。~~

~~試しましたが、そもそも``__cpuid``が使えないです。
ちゃんと``c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Clang 3.7\include\Intrin.h``に~~

```cpp:Intrin.h_l.74
static __inline__
void __cpuid(int[4], int);
static __inline__
void __cpuidex(int[4], int, int);
```

~~とかいてあるにもかかわらず~~

```
error LNK2019: 未解決の外部シンボル "void __cdecl __cpuid(int * const,int)" (?__cpuid@@YAXQAHH@Z) が関数 "struct regs_t __cdecl get_cpuid(unsigned int)" (?get_cpuid@@YA?AUregs_t@@I@Z) で参照されました。
```

~~おい、どういうことだ、Link errorにするくらいなら最初っからヘッダーつけんなばーか。しかもヘッダーでは~~

```cpp:Intrin.h_l.56
#ifdef __cplusplus
extern "C" {
#endif
```
~~されてんのにlink error messageが``?__cpuid@@YAXQAHH@Z``ってお前何を探してやがるんだ~~

と言った状況からはClangが3.8にあがった5月版から改善したようで、例えば``__cpuid``は使えるようになりました(GNU Styleの5引数の``__get_cpuid``のみで``__cpuid``はただのalias)。

SIMD Intrinsic は相変わらず使えません。というのも、コンパイラに[``Intrinsic not yet implemented``とか言われます](https://connect.microsoft.com/VisualStudio/feedback/details/2782472/clang-c2-ice-with-mm-packs-epi32-and-mm-madd-epi16-intrinsics)
ヘッダー見てる感じVS-Style、GNU-styleどっちも使えそうだったから(例えば``_rdrand32_step``と``__builtin_ia32_rdrand32_step``)行けるのかとおもいきやダメでした。``-msse2``とか``-mrdrnd``とか``-march=native``も効きませんでしたとさ。

### tchar

Clang with Microsoft CodeGenを使う際、**tchar.hをWindows.hより先にincludeしてはならない**

なぜかというと、

>C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt\tchar.h

がincludeされるのだが、

```c:tchar.h_175-180行目
#ifndef _TCHAR_DEFINED
#if !__STDC__
typedef wchar_t     TCHAR;
#endif  /* !__STDC__ */
#define _TCHAR_DEFINED
#endif  /* _TCHAR_DEFINED */
```

```c:tchar.h_1261-1266行目
#ifndef _TCHAR_DEFINED
#if !__STDC__
typedef char            TCHAR;
#endif  /* !__STDC__ */
#define _TCHAR_DEFINED
#endif  /* _TCHAR_DEFINED */
```

```c:tchar.h_2090-2095行目
#ifndef _TCHAR_DEFINED
#if !__STDC__
typedef char            TCHAR;
#endif  /* !__STDC__ */
#define _TCHAR_DEFINED
#endif  /* _TCHAR_DEFINED */
```

のようになっていて、TCHAR型が使えない。なぜならClang with Microsoft CodeGenでは``__STDC__``マクロがdefineされるからだ。逆に言えば、MSVCは

>https://msdn.microsoft.com/ja-jp/library/b0084kay.aspx
>ANSI/ISO C99 規格への準拠を示します。 /Za コンパイラ オプションが指定され、C++ コードをコンパイルしていない場合のみ、整数リテラルの定数 1 として定義されます。それ以外の場合は、定義されません。

と、定義されていないので使えるのである。しかも

```c
#define _TCHAR_DEFINED
```

の一文のせいで、例えばWindows.hをincludeした時にこっちのTCHAR型まで無効化するのである。おのれMS。

コメントで、**コンパイラオプションで**マクロ``__STDC__``を0にdefineするといった方法が紹介されています。

~~https://connect.microsoft.com/VisualStudio/Feedback
http://blogs.msdn.com/b/vcblog/archive/2015/12/04/introducing-clang-with-microsoft-codegen-in-vs-2015-update-1.aspx
どっちにバグレポ投げればいいの？~~

~~https://connect.microsoft.com/VisualStudio/feedback/details/2122400~~
[(いつの間にかMSのバグ報告の場所が変わってしかもURL死にやがったのでWeb Archiveでどうぞー)](http://web.archive.org/web/20160208103549/https://connect.microsoft.com/VisualStudio/feedback/details/2122400)
**MSにバグレポ投げました**。この英語力のなさ、どうにかしたい。

追記

>投稿者: James [MSFT]、投稿日時: 2016/01/12 6:06
>Hello,

>Thank you for reporting this issue. We've fixed this; the fix will appear in a future release of the Windows SDK.

>Sincerely,

>James McNellis
>Visual C++ Libraries
>james.mcnellis@microsoft.com

ほう、fixされるらしいぞ。やったね。でもWindows SDKの更新ってそれいつよ。

~~Debug~~

ちゃんとステップ実行もできます。~~できるんですが！逆アセンブルウィンドウも使えますが！何故にや知らん、スタックトレースしてくれません。辛い。~~**``-g``つけてコンパイルしてませんでした**、ちゃんと動きます

~~例外~~

>~~http://blogs.msdn.com/b/vcblog/archive/2015/12/04/introducing-clang-with-microsoft-codegen-in-vs-2015-update-1.aspx
>When changing from MSVC toolset, exception handling is currently off-by-default even though exception handling works. The developer can override this switch manually. The default will change in the next release.~~

~~例外を使うコードはデフォルト設定では使えない。上にも書いたとおり、構成プロパティ→C/C++→コード生成→C++の例外を有効にする を「はい」にする必要がある。次のリリースではデフォルトで有効になるようですが。~~

~~またx86(Win32)アーキテクチャの例外処理はバグが多いと誰かが言っていたので避けたほうが賢明かもしれない。~~

### `'_Ty' does not refer to a value`

Visual Studio 2017(`_MSC_VER`が`1911`らへん)の場合、

```
In file included from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\exception:7:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(898,47): error : '_Ty' does not refer to a value
                : bool_constant<__is_trivially_destructible(_Ty)>
                                                            ^
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(896,16) :  note: declared here
template<class _Ty>
               ^
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(899,2): error : expected class name
        {       // determine whether _Ty has a trivial destructor
        ^
2 errors generated.
```

のようなエラーが出ます。


これはClang with Microsoft CodeGenのclangがVSのコンパイラ拡張の`__is_trivially_destructible`に対応していないため。[新しいclangを自力で入れて](https://hg.mozilla.org/mozilla-central/rev/9072ae5dd4f8)使えば大丈夫っぽいです。

- https://bugzilla.mozilla.org/show_bug.cgi?id=1423307
- https://stackoverflow.com/questions/47680258/clang-c2-on-visual-studio-15-5-bool-constant-is-trivially-destructible-ty-e

# Breaking Change

プラットフォームツールセットの名前が``Clang 3.7 with Microsoft CodeGen (v140_clang_3_7)``から``Visual Studio 2015 - Clang with Microsoft CodeGen (v140_clang_c2)``に変更になっています。プロジェクトの設定を変えないとコンパイルできなくなっていますのでご注意。

# 結論

- Clang with Microsoft CodeGenの導入に成功し、それを記事にしたことでClangの存在を世に広める事ができた(?)
- Clang with Microsoft CodeGenという取り組みを伝えることで、最近はMSも頑張ってることを伝えることができた
- おのれMS
- __cpuid使わせろ

# C++初心者Advent Calendar 2015
この記事は[C++初心者Advent Calendar 2015](http://www.adventar.org/calendars/922) 9日目の記事です
[<< 8日目 | C++のポインタ渡しと参照渡しの使い分け](http://cocodrips.hateblo.jp/entry/2015/12/08/221722) || [10日目 | テンプレートでコケた話 >>](http://qiita.com/Roadagain/items/8ec4ab4ba6c46fe0ce41)
[17日目 | C99からC++14を駆け抜けるC++講座 >>](http://qiita.com/yumetodo/items/e49a673afd9a3ecb81a8)

次はringoh72さんのテンプレートでコケた話ですね。今日も私はtemplateには苦しめられたので楽しみです。よろしくお願いします。