# 機能設計書 84-pp-trace

## 概要

本ドキュメントは、pp-traceツールの機能設計について記述する。pp-traceは、Clangプリプロセッサのコールバック活動をトレースし、YAML形式でテキスト出力するツールである。

### 本機能の処理概要

pp-traceは、Clang PreprocessorのPPCallbacksクラスを継承したトラッカーを使用して、プリプロセッサの各種コールバック（ファイルインクルード、マクロ展開、条件分岐等）を記録し、YAML形式で出力する。

**業務上の目的・背景**：プリプロセッサの動作理解やデバッグ、Clang PPCallbacksメカニズムのテストに使用される。インクルード順序の確認、マクロ展開の追跡、条件コンパイルの動作確認などに役立つ。

**機能の利用シーン**：
- インクルードガードの動作確認
- マクロ展開の追跡とデバッグ
- 条件コンパイル（#if/#ifdef等）の解析
- ビルドシステムの依存関係分析
- Clang PPCallbacksの動作テスト

**主要な処理内容**：
1. ソースファイルのプリプロセス実行
2. PPCallbacksの各コールバック関数をオーバーライド
3. コールバック呼び出し情報をCallbackCall構造体に記録
4. 終了時にYAML形式で出力

**関連システム・外部連携**：Clang LibTooling API、Clang Lexer/Preprocessor API。

**権限による制御**：特になし。読み取り対象ファイルへのアクセス権限と出力ファイルへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIツール | 主画面 | コマンドライン経由での実行 |

## 機能種別

解析 / デバッグ支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -callbacks | string | No | トレースするコールバックのGlobパターン（デフォルト: "*"） | 有効なGlobパターン |
| -output | string | No | 出力ファイル名（デフォルト: "-" = stdout） | - |
| source files | string list | Yes | 対象ソースファイル | ファイルが存在すること |
| -- | string list | No | コンパイラに渡すオプション | - |

### 入力データソース

- ソースファイル（.h, .c, .cpp等）
- compilation database（compile_commands.json、オプション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| トレース出力 | YAML | プリプロセッサコールバックのトレース情報 |

### 出力先

- -output指定時：指定ファイル
- デフォルト：標準出力

### 出力形式例

```yaml
---
- Callback: FileChanged
  Loc: "test.cpp:1:1"
  Reason: EnterFile
  FileType: C_User
  PrevFID: (invalid)
- Callback: MacroDefined
  MacroNameTok: MAX
  MacroDirective: "define MAX 100"
...
```

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の解析
   └─ CommonOptionsParserでオプションを取得

2. コールバックフィルタの解析
   └─ -callbacksオプションをGlobPatternに変換
   └─ "-"プレフィックスで除外パターンを設定

3. 出力ファイルの準備
   └─ -output指定時はファイルを開く
   └─ デフォルトは標準出力

4. PPTraceFrontendActionFactoryの作成
   └─ フィルタと出力ストリームを設定

5. ClangToolの実行
   └─ Tool.run(&Factory)で解析開始

6. ソースファイルごとのプリプロセス
   └─ PPCallbacksTrackerをPreprocessorに登録
   └─ 各コールバックでCallbackCallを記録

7. ソースファイル終了時のYAML出力
   └─ EndSourceFileActionで蓄積データを出力
   └─ "---" ... "..." 形式で出力

8. 全ファイル処理完了
   └─ 出力ファイルをkeep（正常終了時）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C[コールバックフィルタ解析]
    C --> D{フィルタ有効?}
    D -->|Yes| E[GlobPattern生成]
    D -->|No| F[デフォルト: * all]
    E --> G[出力ファイル準備]
    F --> G
    G --> H[ClangTool実行]
    H --> I[PPTraceAction生成]
    I --> J[CreateASTConsumer]
    J --> K[PPCallbacksTracker登録]
    K --> L[プリプロセス実行]
    L --> M{コールバック発生}
    M -->|Yes| N{フィルタ通過?}
    N -->|Yes| O[CallbackCall記録]
    N -->|No| M
    O --> M
    M -->|EOF| P[EndSourceFileAction]
    P --> Q[YAML出力]
    Q --> R{次のファイル?}
    R -->|Yes| I
    R -->|No| S{エラー?}
    S -->|Yes| T[エラー終了]
    S -->|No| U[ファイルkeep]
    U --> V[終了]
    T --> V
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトフィルタ | 未指定時は全コールバック（"*"）をトレース | -callbacks未指定時 |
| BR-02 | 除外フィルタ | "-"プレフィックスでコールバックを除外 | 例: "-Macro*" |
| BR-03 | 順序処理 | フィルタは指定順に処理され、後のパターンが優先 | 複数パターン指定時 |

### トレース対象コールバック

- **ファイル関連**: FileChanged, FileSkipped, InclusionDirective, moduleImport, EndOfMainFile
- **プラグマ関連**: PragmaDirective, PragmaComment, PragmaDebug, PragmaMessage, PragmaDiagnostic等
- **マクロ関連**: MacroExpands, MacroDefined, MacroUndefined, Defined
- **条件分岐関連**: If, Elif, Ifdef, Ifndef, Else, Endif, SourceRangeSkipped

## データベース操作仕様

該当なし（ファイルベースの操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | Globエラー | 無効なGlobパターン | 正しいパターンを指定 |
| 1 | ファイルエラー | 出力ファイルを開けない | パスと権限を確認 |
| - | コンパイルエラー | ソースファイルの構文エラー | ソースを修正 |

### リトライ仕様

リトライは行わない。エラー時は即座に終了。

## トランザクション仕様

該当なし。ただし、エラー時は出力ファイルは保持されない（Out.keep()が呼ばれない）。

## パフォーマンス要件

特に規定なし。プリプロセス処理時間に比例。

## セキュリティ考慮事項

- ソースファイルへの読み取りアクセスが必要
- 出力ファイルへの書き込みアクセスが必要
- 機密情報がトレースに含まれる可能性（マクロ定義等）

## 備考

- 出力はYAMLドキュメント形式（---で開始、...で終了）
- ファイルごとに別のYAMLドキュメントとして出力
- コールバック引数は人間が読みやすい高レベル文字列形式で記録

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PPCallbacksTracker.h | `clang-tools-extra/pp-trace/PPCallbacksTracker.h` | Argument, CallbackCall, PPCallbacksTrackerクラスの定義 |

**読解のコツ**: Argumentは名前と値のペア。CallbackCallはコールバック名と引数リスト。PPCallbacksTrackerはPPCallbacksを継承し、全コールバックをオーバーライド。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PPTrace.cpp | `clang-tools-extra/pp-trace/PPTrace.cpp` | main関数とPPTraceAction実装 |

**主要処理フロー**:
1. **128-134行目**: CommonOptionsParserでコマンドライン解析
2. **136-148行目**: -callbacksオプションをGlobPatternに変換
3. **151-152行目**: ClangTool初期化
4. **154-158行目**: 出力ファイル準備
5. **158-159行目**: PPTraceFrontendActionFactory作成と実行
6. **79-109行目**: PPTraceActionクラス - ASTConsumer生成とYAML出力

#### Step 3: コールバックトラッキングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PPCallbacksTracker.cpp | `clang-tools-extra/pp-trace/PPCallbacksTracker.cpp` | 各コールバックの実装とヘルパー関数 |

**主要処理フロー**:
- 各PPCallbacksメソッドのオーバーライド
- beginCallback()でCallbackCall開始
- appendArgument()で引数を追加
- フィルタ判定による出力抑制

### プログラム呼び出し階層図

```
main (PPTrace.cpp)
    │
    ├─ CommonOptionsParser::create
    │
    ├─ GlobPattern::create (フィルタ解析)
    │
    ├─ ToolOutputFile (出力準備)
    │
    └─ ClangTool::run
           │
           └─ PPTraceFrontendActionFactory::create
                  │
                  └─ PPTraceAction
                         │
                         ├─ CreateASTConsumer
                         │      └─ PP.addPPCallbacks(PPCallbacksTracker)
                         │
                         └─ EndSourceFileAction
                                └─ YAML出力

PPCallbacksTracker (プリプロセッサコールバック)
    │
    ├─ FileChanged
    ├─ InclusionDirective
    ├─ MacroDefined
    ├─ MacroExpands
    ├─ MacroUndefined
    ├─ If / Elif / Ifdef / Ifndef
    ├─ Else / Endif
    ├─ Defined
    ├─ SourceRangeSkipped
    └─ (その他多数のコールバック)
           │
           ├─ beginCallback (トレース開始)
           └─ appendArgument (引数追加)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

source files ───┐
                │
-callbacks ─────┼─▶ GlobPattern解析 ─▶ FilterType
                │
                │
                └─▶ ClangTool::run
                          │
                          ▼
                    PPTraceAction
                          │
                          ▼
                    Preprocessor
                          │
                          ▼
                    PPCallbacksTracker
                          │
           ┌──────────────┼──────────────┐
           ▼              ▼              ▼
      FileChanged    MacroDefined    If/Ifdef等
           │              │              │
           └──────────────┼──────────────┘
                          │
                          ▼
                    CallbackCalls[]
                          │
                          ▼
                    EndSourceFileAction
                          │
                          ▼
                    ┌─────────────┐
                    │   YAML出力   │
                    │ ---          │
                    │ - Callback:  │
                    │   ...        │
                    │ ...          │
                    └─────────────┘
                          │
                          ▼
                    -output / stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PPTrace.cpp | `clang-tools-extra/pp-trace/PPTrace.cpp` | ソース | mainエントリーポイント、PPTraceAction実装 |
| PPCallbacksTracker.h | `clang-tools-extra/pp-trace/PPCallbacksTracker.h` | ヘッダ | トラッカークラス定義 |
| PPCallbacksTracker.cpp | `clang-tools-extra/pp-trace/PPCallbacksTracker.cpp` | ソース | コールバック実装 |
| CMakeLists.txt | `clang-tools-extra/pp-trace/CMakeLists.txt` | ビルド | ビルド設定 |
