第二回目はLLVM/Clang/Swiftプロジェクトのコーディングスタイルを紹介していく。いずれのプロジェクトも同一のコーディング規約を採用しているため、まとめて紹介することにする。
LLVM/Clang/Swift
LLVMは今最も熱いコンパイラ基盤。高い最適化能力が特徴。LLVMはC言語コンパイラであるClangのバックエンド技術としても使われている。Clangは高速なコンパイル性能が特徴。ClangプロジェクトではApple社やGoogle社が様々な場面で関わっている。Apple社のSwift言語もLLVMを採用している。なおSwiftの生みの親はLLVMとClangの開発にも関わっている。いずれもC++と呼ばれるプログラミング言語で開発されている。
サンプルコード
namespace ns {
template <typename T>
class ClassName {
const char *Data; // メンバ変数もアッパーキャメルケースで記述
unsigned Length;
public:
ClassName()
: Data(), // コロンは先頭、カンマは末尾に記述
Length() { // メンバを縦方向に揃える
switch (0) { // 波括弧は制御文と同一の行に記述
case 0: // case文をswitchと同一の列に記述
break; // 改行後に処理を記述
}
}
char value() { // 波括弧は改行せずに記述
if (Length == 0) return '\0'; // 波括弧省略・ワンライン化あり
return Data[Length-1]; // 算術演算時には空白を省略する場合がある
}
/// document comment
template <typename U> int setValue(const U &Val,
unsigned N) { // 仮引数毎に改行
const char *D = copy(Val);
Data = D;
if (N != -1 && // 演算子の末尾で改行
N != 0) // このような場面でも波括弧を省略することがある
Length = N;
else {
auto SL = strlen(Data); // 変数名や仮引数名に頭字語を使うことがある
if (SL > 9); // 常に左辺値を左側に記述
}
return 0;
}
};
} // namespace ns
コーディングスタイルや開発スタイルの特徴
大文字で始まる変数名が印象的。理由は明確にされていないが、おそらくインパクト性の向上やメンバ関数との区別、名前衝突を避ける意図があると思われる。一文字変数の利用やif文のインライン記法、波括弧の省略記法など、レガシー/伝統的な開発スタイルも数多く取り入れられている。流行に惑わされない保守的なスタイルを持ちながらも、書き手の理想を追求するリベラルなスタイルという印象を受ける。要はカオスで癖が強い。
カテゴリ | スタイル |
---|---|
開発スタイル | |
インデント | ソフトタブ(2文字幅) |
空行 | インデント無し |
ソースコードの幅 | 制限あり(80文字)※ 印刷時や端末での表示を意識 |
適切な改行 | 少なめ、詰まったコードが多い |
波括弧の省略 | あり |
波括弧の改行 | あり(開始括弧の前で改行) |
if文のインライン化 | あり(波括弧の省略もあり) |
一文字変数 | あり(大文字) |
アクセサ | ゲッター/セッター(`getValue() / setValue()`) |
ドキュメントコメント | `/// `を利用 |
コード整列 | 基本的なもののみ(仮引数、OR演算、コメント) |
ヘッダファイル | ソースファイルと別ディレクトリで管理(`./include`) |
プログラミング作法 | |
goto文 | 多用する |
case文 | switch文と同一の列に記述 |
ヨーダ記法 | 無し。大なり比較でも左辺値優先(`v > 9`) |
演算処理の空白 | 混在(`a[n-1]`, `v+1`, `a + b`) |
改行時の演算子 | 後置(改行の直前に記述) |
命名規則 | |
クラス名 | アッパーキャメルケース |
メンバ変数 | アッパーキャメルケース |
メンバ関数 | ローワーキャメルケース |
仮引数 | アッパーキャメルケース |
一時変数 | アッパーキャメルケース |
略称 | 明確な物のみ使う(Loc, Len, tok, Stmt) |
頭字語 | 良く使う(`AbCd` → `AC`) |
C++スタイル | |
参照 | 変数側に詰める(`int &v;`) |
ポインタ | 変数側に詰める(`int *v;`) |
const左辺値参照 | constを型名に対して前置する(`const T &v;`) |
プライベートメンバ変数 | クラススコープの先頭で宣言 |
コンストラクタ | クラススコープの前方で宣言 |
テンプレート | 空白あり、typename使用(`template <typename T>`) |
生ポインタ | 使う(デストラクタでnew/deleteする) |
スマートポインタ | 使う(unique_ptr/shared_ptr) |
演算子オーバロード | あまり使わない |
純粋仮想関数 | 基本使わない |
例外 | 使わない |
RTTI | 使わない(実行ファイルの肥大化を避ける意図) |
C++スタイルキャスト | dynamic_castのみ使わない(dyn_castを独自実装) |
前置/後置インクリメント | バリバリ使う |
using namespace | ユーザ定義の空間をファイルスコープに取り込む(`using namespace llvm;`) |
コーディング規約
LLVM Coding Standards — LLVM 6 documentation(https://llvm.org/docs/CodingStandards.html)
ソースコード・リポジトリ
- LLVM(
https://git.llvm.org/git/llvm
) - Swift(https://github.com/apple/swift)