Skip to main content

libperl_macrogen/
rust_codegen.rs

1//! Rust コード生成モジュール
2//!
3//! 型推論結果から Rust コードを生成する。
4
5use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
6use std::io::{self, Write};
7
8use crate::ast::{AssertKind, AssignOp, BinOp, BlockItem, CompoundStmt, Declaration, DeclSpecs, DerivedDecl, Expr, ExprKind, ForInit, FunctionDef, Initializer, ParamDecl, Stmt, TypeSpec};
9
10use crate::intern::InternedStr;
11use crate::enum_dict::EnumDict;
12use crate::infer_api::InferResult;
13use crate::intern::StringInterner;
14use crate::macro_infer::{MacroInferContext, MacroInferInfo, MacroParam, ParseResult};
15use crate::rust_decl::RustDeclDict;
16use crate::syn_codegen::normalize_parens;
17use crate::unified_type::UnifiedType;
18use crate::sexp::SexpPrinter;
19
20/// bindings.rs から抽出した codegen 用情報
21#[derive(Debug, Default, Clone)]
22pub struct BindingsInfo {
23    /// 配列型の extern static 変数名の集合
24    pub static_arrays: HashSet<String>,
25    /// extern static 変数名 → 型文字列("[T; N]" や "T" 等)
26    /// 配列の要素型抽出に使う。`static_array_element_type` も参照。
27    pub static_types: HashMap<String, String>,
28    /// ビットフィールドのメソッド名集合(構造体名 → メソッド名セット)
29    pub bitfield_methods: HashMap<String, HashSet<String>>,
30}
31
32impl BindingsInfo {
33    /// RustDeclDict から BindingsInfo を構築
34    pub fn from_rust_decl_dict(dict: &RustDeclDict) -> Self {
35        Self {
36            static_arrays: dict.static_arrays.clone(),
37            static_types: dict.static_types.clone(),
38            bitfield_methods: dict.bitfield_methods.clone(),
39        }
40    }
41
42    /// `static_arrays` に含まれる名前の **配列要素型** を返す。
43    /// `static_types[name]` が `"[T; N]"` 形式なら T を取り出す。
44    /// 抽出できなかったら None(呼出側でフォールバック)。
45    pub fn static_array_element_type(&self, name: &str) -> Option<String> {
46        let ty = self.static_types.get(name)?;
47        let s = ty.trim();
48        let s = s.strip_prefix('[')?;
49        let s = s.strip_suffix(']')?;
50        let semi = s.rfind(';')?;
51        Some(s[..semi].trim().to_string())
52    }
53}
54
55/// libc crate から提供される関数名のリスト
56/// codegen がそのまま関数呼び出しとして出力する関数のみ
57/// (`__builtin_expect` 等の codegen 変換済み関数は含めない)
58const LIBC_FUNCTIONS: &[&str] = &[
59    "strcmp", "strlen", "strncmp", "strcpy", "strncpy",
60    "memset", "memchr", "memcpy", "memmove",
61];
62
63/// 既知の libc 関数の引数型 (bindings.rs に登録されない関数を補完)。
64///
65/// 呼出側は `as *mut c_char` で渡しがちだが libc は `*mut c_void` を要求する。
66/// ハードコードした型を `get_callee_param_type_extended` 経由で引くと、
67/// 自動 as-cast (cast_arg_syn_if_needed の void-pointer 分岐) に乗る。
68fn libc_fn_param_type(func_name: &str, arg_index: usize) -> Option<UnifiedType> {
69    match (func_name, arg_index) {
70        // memset(void *s, int c, size_t n)
71        ("memset", 0) => Some(UnifiedType::from_rust_str("*mut c_void")),
72        ("memset", 1) => Some(UnifiedType::from_rust_str("c_int")),
73        ("memset", 2) => Some(UnifiedType::from_rust_str("usize")),
74        // memcpy(void *dest, const void *src, size_t n)
75        ("memcpy", 0) | ("memmove", 0) => Some(UnifiedType::from_rust_str("*mut c_void")),
76        ("memcpy", 1) | ("memmove", 1) => Some(UnifiedType::from_rust_str("*const c_void")),
77        ("memcpy", 2) | ("memmove", 2) => Some(UnifiedType::from_rust_str("usize")),
78        // memchr(const void *s, int c, size_t n)
79        ("memchr", 0) => Some(UnifiedType::from_rust_str("*const c_void")),
80        ("memchr", 1) => Some(UnifiedType::from_rust_str("c_int")),
81        ("memchr", 2) => Some(UnifiedType::from_rust_str("usize")),
82        // memcmp(const void *s1, const void *s2, size_t n)
83        ("memcmp", 0) | ("memcmp", 1) => Some(UnifiedType::from_rust_str("*const c_void")),
84        ("memcmp", 2) => Some(UnifiedType::from_rust_str("usize")),
85        // strcmp / strncmp: *const c_char
86        ("strcmp", 0) | ("strcmp", 1) | ("strncmp", 0) | ("strncmp", 1) =>
87            Some(UnifiedType::from_rust_str("*const c_char")),
88        ("strncmp", 2) => Some(UnifiedType::from_rust_str("usize")),
89        // strlen: *const c_char
90        ("strlen", 0) => Some(UnifiedType::from_rust_str("*const c_char")),
91        // strcpy/strncpy: dest *mut, src *const c_char
92        ("strcpy", 0) | ("strncpy", 0) => Some(UnifiedType::from_rust_str("*mut c_char")),
93        ("strcpy", 1) | ("strncpy", 1) => Some(UnifiedType::from_rust_str("*const c_char")),
94        ("strncpy", 2) => Some(UnifiedType::from_rust_str("usize")),
95        _ => None,
96    }
97}
98
99/// コード生成時に解決可能なシンボルの集合
100///
101/// bindings.rs、マクロ辞書、inline 関数辞書、ビルトイン関数等から
102/// 既知のシンボル名を収集する。コード生成時に `ExprKind::Ident` が
103/// この集合に含まれない場合、未解決シンボルとして検出する。
104pub struct KnownSymbols {
105    names: HashSet<String>,
106}
107
108impl KnownSymbols {
109    /// InferResult から既知シンボル集合を構築
110    pub fn new(result: &InferResult, interner: &StringInterner) -> Self {
111        let mut names = HashSet::new();
112
113        // bindings.rs の関数名
114        if let Some(ref dict) = result.rust_decl_dict {
115            for name in dict.fns.keys() {
116                names.insert(name.clone());
117            }
118            for name in dict.consts.keys() {
119                names.insert(name.clone());
120            }
121            for name in dict.types.keys() {
122                names.insert(name.clone());
123            }
124            for name in dict.structs.keys() {
125                names.insert(name.clone());
126            }
127            for name in &dict.enums {
128                names.insert(name.clone());
129            }
130            for name in &dict.statics {
131                names.insert(name.clone());
132            }
133            for name in &dict.static_arrays {
134                names.insert(name.clone());
135            }
136        }
137
138        // マクロ名(関数呼び出しとして保持されるもの)
139        for (name_id, info) in &result.infer_ctx.macros {
140            let name_str = interner.get(*name_id);
141            // 関数マクロのみ既知とする(オブジェクトマクロは除外)
142            // オブジェクトマクロ名(例: `n`, `s`, `c`)を登録すると、
143            // ジェネリック誤検出で残ったパラメータ参照が既知扱いになってしまう
144            if info.has_body && info.is_function {
145                names.insert(name_str.to_string());
146            }
147        }
148
149        // inline 関数名
150        for (name_id, _) in result.inline_fn_dict.iter() {
151            let name_str = interner.get(*name_id);
152            names.insert(name_str.to_string());
153        }
154
155        // ビルトイン関数(codegen が変換・除去するもの)
156        let builtins = [
157            "__builtin_expect",
158            "__builtin_offsetof",
159            "offsetof",
160            "__builtin_types_compatible_p",
161            "__builtin_constant_p",
162            "__builtin_choose_expr",
163            "__builtin_unreachable",
164            "__builtin_trap",
165            "__builtin_assume",
166            "__builtin_bswap16",
167            "__builtin_bswap32",
168            "__builtin_bswap64",
169            "__builtin_popcount",
170            "__builtin_clz",
171            "__builtin_ctz",
172            "pthread_mutex_lock",
173            "pthread_mutex_unlock",
174            "pthread_rwlock_rdlock",
175            "pthread_rwlock_wrlock",
176            "pthread_rwlock_unlock",
177            "pthread_getspecific",
178            "pthread_cond_wait",
179            "pthread_cond_signal",
180            "getenv",
181            "ASSERT_IS_LITERAL",
182            "ASSERT_IS_PTR",
183            "ASSERT_NOT_PTR",
184        ];
185        for name in builtins {
186            names.insert(name.to_string());
187        }
188
189        // libc 関数(use libc::{...} で利用可能になる)
190        for name in LIBC_FUNCTIONS {
191            names.insert(name.to_string());
192        }
193
194        // 自動生成 static const 配列名(`static_array_emitter.rs` 由来)
195        // 注: struct/typedef alias 名は `generate()` 側で実際に出力できた名前のみ
196        // 後から `insert()` する。事前にここで全部入れると未生成の型を参照する
197        // コードを「既知」とみなして compile error を起こす可能性がある。
198        for (name_id, _) in result.global_const_dict.iter() {
199            names.insert(interner.get(*name_id).to_string());
200        }
201
202        // Rust プリミティブ / 標準識別子
203        let rust_primitives = [
204            "true", "false", "std", "crate", "self", "super",
205            "null_mut", "null",
206            "PerlInterpreter", "my_perl",
207            // 出力ヘッダで `type X = Y;` 定義しているもの
208            // (`generate_use_statements` 参照)
209            "size_t", "ssize_t", "SSize_t",
210            // std::ffi 由来(use 文で import 済み)
211            "c_void", "c_char", "c_uchar", "c_int", "c_uint",
212            "c_long", "c_ulong", "c_short", "c_ushort",
213        ];
214        for name in rust_primitives {
215            names.insert(name.to_string());
216        }
217
218        Self { names }
219    }
220
221    /// シンボル名が既知かどうかチェック
222    fn contains(&self, name: &str) -> bool {
223        self.names.contains(name)
224    }
225
226    /// 既知シンボルとして名前を追加
227    pub fn insert(&mut self, name: String) {
228        self.names.insert(name);
229    }
230}
231
232/// Rust の予約語リスト(strict keywords + reserved keywords)
233/// 注: true/false はリテラルなので含めない
234const RUST_KEYWORDS: &[&str] = &[
235    // Strict keywords (true/false は除外 - リテラルなのでエスケープ不要)
236    "as", "async", "await", "break", "const", "continue", "crate", "dyn",
237    "else", "enum", "extern", "fn", "for", "if", "impl", "in",
238    "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return",
239    "self", "Self", "static", "struct", "super", "trait", "type",
240    "unsafe", "use", "where", "while",
241    // Reserved keywords
242    "abstract", "become", "box", "do", "final", "gen", "macro", "override",
243    "priv", "try", "typeof", "unsized", "virtual", "yield",
244];
245
246/// 識別子を Rust コードに変換
247///
248/// - Rust の予約語は r# を付ける
249/// - C のプリプロセッサマクロは Rust の同等品に変換
250fn escape_rust_keyword(name: &str) -> String {
251    match name {
252        // C プリプロセッサマクロ → Rust マクロ
253        "__FILE__" => "file!()".to_string(),
254        "__LINE__" => "line!()".to_string(),
255        // Rust 予約語はエスケープ
256        _ if RUST_KEYWORDS.contains(&name) => format!("r#{}", name),
257        // その他はそのまま
258        _ => name.to_string(),
259    }
260}
261
262/// 単語境界を考慮した文字列置換
263///
264/// 型パラメータ名の置換時に、部分文字列一致を避けるために使用。
265/// 例: "XV" を "T" に置換するとき、"XPVNV" は変更しない。
266fn replace_word(s: &str, word: &str, replacement: &str) -> String {
267    if word.is_empty() {
268        return s.to_string();
269    }
270    let mut result = String::with_capacity(s.len());
271    let mut start = 0;
272    let bytes = s.as_bytes();
273    let word_bytes = word.as_bytes();
274    while let Some(pos) = s[start..].find(word) {
275        let abs_pos = start + pos;
276        // 前方の境界チェック
277        let before_ok = abs_pos == 0 || !is_ident_char(bytes[abs_pos - 1]);
278        // 後方の境界チェック
279        let after_pos = abs_pos + word.len();
280        let after_ok = after_pos >= bytes.len() || !is_ident_char(bytes[after_pos]);
281
282        if before_ok && after_ok {
283            result.push_str(&s[start..abs_pos]);
284            result.push_str(replacement);
285            start = after_pos;
286        } else {
287            result.push_str(&s[start..abs_pos + word_bytes.len()]);
288            start = abs_pos + word_bytes.len();
289        }
290    }
291    result.push_str(&s[start..]);
292    result
293}
294
295/// 識別子を構成する文字かどうか
296fn is_ident_char(b: u8) -> bool {
297    b.is_ascii_alphanumeric() || b == b'_'
298}
299
300/// 二項演算子を Rust 形式に変換
301fn bin_op_to_rust(op: BinOp) -> &'static str {
302    match op {
303        BinOp::Add => "+",
304        BinOp::Sub => "-",
305        BinOp::Mul => "*",
306        BinOp::Div => "/",
307        BinOp::Mod => "%",
308        BinOp::BitAnd => "&",
309        BinOp::BitOr => "|",
310        BinOp::BitXor => "^",
311        BinOp::Shl => "<<",
312        BinOp::Shr => ">>",
313        BinOp::Lt => "<",
314        BinOp::Gt => ">",
315        BinOp::Le => "<=",
316        BinOp::Ge => ">=",
317        BinOp::Eq => "==",
318        BinOp::Ne => "!=",
319        BinOp::LogAnd => "&&",
320        BinOp::LogOr => "||",
321    }
322}
323
324/// 代入演算子を Rust 形式に変換
325fn assign_op_to_rust(op: AssignOp) -> &'static str {
326    match op {
327        AssignOp::Assign => "=",
328        AssignOp::MulAssign => "*=",
329        AssignOp::DivAssign => "/=",
330        AssignOp::ModAssign => "%=",
331        AssignOp::AddAssign => "+=",
332        AssignOp::SubAssign => "-=",
333        AssignOp::ShlAssign => "<<=",
334        AssignOp::ShrAssign => ">>=",
335        AssignOp::AndAssign => "&=",
336        AssignOp::XorAssign => "^=",
337        AssignOp::OrAssign => "|=",
338    }
339}
340
341/// 文字をエスケープ
342fn escape_char(c: u8) -> String {
343    match c {
344        b'\'' => "\\'".to_string(),
345        b'\\' => "\\\\".to_string(),
346        b'\n' => "\\n".to_string(),
347        b'\r' => "\\r".to_string(),
348        b'\t' => "\\t".to_string(),
349        c if c.is_ascii_graphic() || c == b' ' => (c as char).to_string(),
350        c => format!("\\x{:02x}", c),
351    }
352}
353
354/// 文字列をエスケープ
355fn escape_string(s: &[u8]) -> String {
356    s.iter().map(|&c| escape_char(c)).collect()
357}
358
359/// C の `(void)` 単独パラメータ = 引数なし、を判定する。
360///
361/// K&R 方式との互換のため、C では明示的に `void` を単一パラメータとして
362/// 書くことで「引数なし」を宣言する慣習がある (例: `int foo(void)`)。
363/// Rust には対応する概念がなく、そのまま `_: ()` に訳すと呼出側との
364/// 食い違いが起きるため、**パラメータなし** として生成する。
365fn is_void_only_param_list(params: &[ParamDecl]) -> bool {
366    if params.len() != 1 {
367        return false;
368    }
369    let p = &params[0];
370    // 名前付きでない(無名引数)こと、ポインタ派生していないこと、
371    // かつ単独の TypeSpec::Void であること。
372    let declarator_is_trivial = match &p.declarator {
373        None => true,
374        Some(d) => d.name.is_none() && d.derived.is_empty(),
375    };
376    let specs_is_void = p.specs.type_specs.len() == 1
377        && matches!(p.specs.type_specs[0], TypeSpec::Void);
378    declarator_is_trivial && specs_is_void
379}
380
381/// 式がゼロ定数かどうかを判定
382fn is_zero_constant(expr: &Expr) -> bool {
383    match &expr.kind {
384        ExprKind::IntLit(0) => true,
385        ExprKind::UIntLit(0) => true,
386        _ => false,
387    }
388}
389
390/// 式が bool として扱える形式かどうかを判定
391///
392/// キャスト `(expr as bool)` を含む場合も true を返す
393pub fn is_boolean_expr(expr: &Expr) -> bool {
394    match &expr.kind {
395        ExprKind::Binary { op, .. } => matches!(op,
396            BinOp::Lt | BinOp::Gt | BinOp::Le | BinOp::Ge |
397            BinOp::Eq | BinOp::Ne | BinOp::LogAnd | BinOp::LogOr
398        ),
399        // (expr as bool) も bool を返す
400        ExprKind::Cast { type_name, .. } => {
401            // TypeSpec が Bool かチェック
402            type_name.specs.type_specs.iter().any(|ts| {
403                matches!(ts, TypeSpec::Bool)
404            })
405        }
406        // LogNot は常に bool を返す(if 式として生成される)
407        ExprKind::LogNot(_) => true,
408        // 三項演算子: 両 arm が bool なら全体も bool。
409        // <=5.34 の cBOOL は `((c) ? (bool)1 : (bool)0)` で、arm は
410        // (bool) キャストにより bool として生成される。ここで ternary を
411        // 非 bool と誤分類すると外側に更に `!= 0` が付き、Rust では
412        // `bool != {integer}` (E0308) になる (5.36+ は cBOOL が
413        // `((bool)(c))` の単純キャストになったため露出しない)
414        ExprKind::Conditional { then_expr, else_expr, .. } => {
415            is_boolean_expr(then_expr) && is_boolean_expr(else_expr)
416        }
417        _ => false,
418    }
419}
420
421
422/// is_boolean_expr の再帰版: __builtin_expect(cond, val) を透過する
423fn is_boolean_expr_recursive(expr: &Expr, interner: &StringInterner) -> bool {
424    if is_boolean_expr(expr) {
425        return true;
426    }
427    match &expr.kind {
428        ExprKind::Call { func, args } => {
429            if let ExprKind::Ident(name) = &func.kind {
430                if interner.get(*name) == "__builtin_expect" && !args.is_empty() {
431                    return is_boolean_expr_recursive(&args[0], interner);
432                }
433            }
434        }
435        // Cast to bool: 内側が bool なら全体も bool
436        ExprKind::Cast { type_name, expr: inner } => {
437            if type_name.specs.type_specs.iter().any(|ts| matches!(ts, TypeSpec::Bool)) {
438                return true;
439            }
440            return is_boolean_expr_recursive(inner, interner);
441        }
442        _ => {}
443    }
444    false
445}
446
447/// コンテキスト付き bool 式判定: 呼び出し先マクロ/外部関数の戻り値型も考慮
448pub fn is_boolean_expr_with_context(
449    expr: &Expr,
450    bool_return_macros: &HashSet<InternedStr>,
451    bool_return_externals: &HashSet<InternedStr>,
452) -> bool {
453    if is_boolean_expr(expr) {
454        return true;
455    }
456    match &expr.kind {
457        ExprKind::Call { func, .. } => {
458            if let ExprKind::Ident(name) = &func.kind {
459                return bool_return_macros.contains(name)
460                    || bool_return_externals.contains(name);
461            }
462        }
463        ExprKind::MacroCall { name, .. } => {
464            return bool_return_macros.contains(name)
465                || bool_return_externals.contains(name);
466        }
467        _ => {}
468    }
469    false
470}
471
472/// TypeRepr がポインタ型かどうか判定
473fn is_type_repr_pointer(ty: &crate::type_repr::TypeRepr) -> bool {
474    use crate::type_repr::TypeRepr;
475    match ty {
476        TypeRepr::CType { derived, .. } => {
477            derived.iter().any(|d| matches!(d, crate::type_repr::CDerivedType::Pointer { .. }))
478        }
479        TypeRepr::RustType { repr, .. } => {
480            matches!(repr, crate::type_repr::RustTypeRepr::Pointer { .. })
481        }
482        TypeRepr::Inferred(inferred) => {
483            inferred.resolved_type()
484                .map(|r| is_type_repr_pointer(r))
485                .unwrap_or(false)
486        }
487    }
488}
489
490/// 自家生成マクロの param に対する全制約のうち、Tier が最も高い
491/// (=数値が小さい) 非 void TypeRepr のクローンを返す。
492/// `param.expr_id()` および `param_to_exprs` から得た全 ExprId を走査する。
493fn best_constraint_for_macro_param(
494    info: &MacroInferInfo,
495    param: &MacroParam,
496) -> Option<crate::type_repr::TypeRepr> {
497    let mut best: Option<(&crate::type_repr::TypeRepr, u8)> = None;
498
499    // param_constraints (マクロ自身の apidoc パラメータ宣言など) を先に走査する:
500    // tier 同点のとき「自身の宣言」が「呼び出し先由来の制約」に勝つように
501    // (厳密未満 `<` の比較なので先着が優先される)。
502    if let Some(constraints) = info.type_env.get_param_constraints(param.name) {
503        for c in constraints {
504            if c.ty.is_void() { continue; }
505            let tier = c.ty.confidence_tier();
506            if best.is_none() || tier < best.unwrap().1 {
507                best = Some((&c.ty, tier));
508            }
509        }
510    }
511
512    let mut all_expr_ids: Vec<crate::ast::ExprId> = info
513        .type_env
514        .param_to_exprs
515        .get(&param.name)
516        .map(|ids| ids.iter().cloned().collect())
517        .unwrap_or_default();
518    all_expr_ids.push(param.expr_id());
519
520    for expr_id in &all_expr_ids {
521        if let Some(constraints) = info.type_env.expr_constraints.get(expr_id) {
522            for c in constraints {
523                if c.ty.is_void() { continue; }
524                let tier = c.ty.confidence_tier();
525                if best.is_none() || tier < best.unwrap().1 {
526                    best = Some((&c.ty, tier));
527                }
528            }
529        }
530    }
531    best.map(|(t, _)| t.clone())
532}
533
534/// `Expr` を再帰的に走査し、`ExprKind::Ident(name)` のうち `subs` に
535/// マッチするものを `subs[name]` のクローンで置換する。
536///
537/// 用途: 自家生成マクロの本体式に対し、`(param_name → arg_expr)` の
538/// 対応で alpha 置換を行う(C プリプロセッサの token 置換相当)。
539/// `&MACRO(args)` を `&<inlined_body>` に展開するために使う。
540fn substitute_idents(expr: &mut Expr, subs: &HashMap<InternedStr, &Expr>) {
541    if let ExprKind::Ident(name) = &expr.kind {
542        if let Some(replacement) = subs.get(name) {
543            *expr = (*replacement).clone();
544            return;
545        }
546    }
547    match &mut expr.kind {
548        ExprKind::Ident(_)
549        | ExprKind::IntLit(_)
550        | ExprKind::UIntLit(_)
551        | ExprKind::FloatLit(_)
552        | ExprKind::CharLit(_)
553        | ExprKind::StringLit(_)
554        | ExprKind::SizeofType(_)
555        | ExprKind::Alignof(_) => {}
556        ExprKind::Index { expr: e, index } => {
557            substitute_idents(e, subs);
558            substitute_idents(index, subs);
559        }
560        ExprKind::Call { func, args } => {
561            substitute_idents(func, subs);
562            for arg in args {
563                substitute_idents(arg, subs);
564            }
565        }
566        ExprKind::Member { expr: e, .. }
567        | ExprKind::PtrMember { expr: e, .. }
568        | ExprKind::PostInc(e)
569        | ExprKind::PostDec(e)
570        | ExprKind::PreInc(e)
571        | ExprKind::PreDec(e)
572        | ExprKind::AddrOf(e)
573        | ExprKind::Deref(e)
574        | ExprKind::UnaryPlus(e)
575        | ExprKind::UnaryMinus(e)
576        | ExprKind::BitNot(e)
577        | ExprKind::LogNot(e)
578        | ExprKind::Sizeof(e)
579        | ExprKind::Cast { expr: e, .. } => substitute_idents(e, subs),
580        ExprKind::Binary { lhs, rhs, .. }
581        | ExprKind::Assign { lhs, rhs, .. }
582        | ExprKind::Comma { lhs, rhs } => {
583            substitute_idents(lhs, subs);
584            substitute_idents(rhs, subs);
585        }
586        ExprKind::Conditional { cond, then_expr, else_expr } => {
587            substitute_idents(cond, subs);
588            substitute_idents(then_expr, subs);
589            substitute_idents(else_expr, subs);
590        }
591        ExprKind::Assert { condition, .. } => substitute_idents(condition, subs),
592        ExprKind::MacroCall { args, expanded, .. } => {
593            for arg in args {
594                substitute_idents(arg, subs);
595            }
596            substitute_idents(expanded, subs);
597        }
598        ExprKind::BuiltinCall { args, .. } => {
599            for arg in args {
600                if let crate::ast::BuiltinArg::Expr(e) = arg {
601                    substitute_idents(e, subs);
602                }
603            }
604        }
605        ExprKind::CompoundLit { init, .. } => {
606            for item in init {
607                if let crate::ast::Initializer::Expr(e) = &mut item.init {
608                    substitute_idents(e, subs);
609                }
610            }
611        }
612        // StmtExpr 内部は文を含むので alpha 置換は当面非対応(保守的)
613        ExprKind::StmtExpr(_) => {}
614    }
615}
616
617/// 式が「文の位置で値を捨てると `-D warnings` を踏む」形をしているか判定する。
618/// 主な用途: C カンマ `(A, B)` の LHS を `let _ = A;` で包むかの判定。
619///
620/// 該当パターン(wrap が必要):
621/// - trailing-expr 付き block (`{ stmt; expr }`): `unused unary / logical op` の温床
622/// - 論理演算 `&&` / `||` (`unused logical operation`)
623/// - 単項式 `*p` `-x` `!b` 等 (`unused unary operation`)
624///
625/// 該当しないパターン(wrap 不要):
626/// - 関数呼出 / メソッド呼出: 大半の FFI 関数は `()` を返し must_use ではない。
627///   `must_use` 戻り値(`size_of_val` 等)は `(void)cast` 経路で別途処理される
628/// - assert!() や `{ stmt; }` のように `()` を返すと明らかなもの
629/// - 単純な代入 `x = y` (Rust では `()` 型)
630fn expr_yields_value_for_stmt_use(expr: &syn::Expr) -> bool {
631    match expr {
632        syn::Expr::Block(b) => {
633            matches!(b.block.stmts.last(), Some(syn::Stmt::Expr(_, None)))
634        }
635        syn::Expr::Binary(b) => matches!(
636            b.op,
637            syn::BinOp::And(_) | syn::BinOp::Or(_)
638        ),
639        syn::Expr::Unary(_) => true,
640        // パーレン内は中身を見る(`(a || b)` 等)
641        syn::Expr::Paren(p) => expr_yields_value_for_stmt_use(&p.expr),
642        _ => false,
643    }
644}
645
646/// unsigned 型へのキャスト式かどうか判定
647/// 例: "(x as usize)", "(x as u32)"
648fn is_unsigned_cast_expr(expr_str: &str) -> bool {
649    if let Some(pos) = expr_str.rfind(" as ") {
650        let after = &expr_str[pos + 4..].trim_end_matches(')');
651        matches!(*after, "usize" | "u8" | "u16" | "u32" | "u64" | "u128" | "c_uint" | "c_ulong" | "c_ulonglong")
652    } else {
653        false
654    }
655}
656
657/// 指定された型名が unsigned 整数型(プリミティブ + 既知エイリアス)か判定。
658/// 真なら `{ty}::MAX` のような associated const が使える。
659fn is_unsigned_integer_target(ty: &str) -> bool {
660    matches!(ty,
661        "u8" | "u16" | "u32" | "u64" | "u128" | "usize" |
662        "U8" | "U16" | "U32" | "U64" |
663        "UV" | "STRLEN" | "Size_t" | "size_t" | "PERL_UINTMAX_T" |
664        "c_uchar" | "c_ushort" | "c_uint" | "c_ulong" | "c_ulonglong"
665    )
666}
667
668
669/// 式文字列の最外レベルの不要な括弧を除去する。
670/// "(expr)" → "expr" (先頭の '(' と末尾の ')' が対応する場合のみ)
671/// ただしブロック式 "({...})" は除去しない( `{...} op expr` が構文エラーになるため)
672fn strip_outer_parens(s: &str) -> &str {
673    let s = s.trim();
674    if s.len() < 2 || !s.starts_with('(') || !s.ends_with(')') {
675        return s;
676    }
677    // 先頭の '(' と末尾の ')' が対応するかチェック
678    let inner = &s[1..s.len() - 1];
679    // ブロック式 ({...}) は strip しない
680    if inner.trim_start().starts_with('{') {
681        return s;
682    }
683    let mut depth = 0i32;
684    for ch in inner.chars() {
685        match ch {
686            '(' | '{' | '[' => depth += 1,
687            ')' | '}' | ']' => {
688                depth -= 1;
689                if depth < 0 {
690                    // 内部で閉じ括弧が余る → 先頭と末尾は非対応
691                    return s;
692                }
693            }
694            _ => {}
695        }
696    }
697    if depth == 0 {
698        inner
699    } else {
700        s
701    }
702}
703
704/// 式が NULL リテラル(整数 0 または (void*)0 のような Cast)かどうか判定
705/// assert(expr || !"message") パターンの RHS からメッセージ文字列を抽出
706fn extract_assert_message(expr: &Expr) -> Option<String> {
707    if let ExprKind::LogNot(inner) = &expr.kind {
708        if let ExprKind::StringLit(bytes) = &inner.kind {
709            return Some(String::from_utf8_lossy(bytes).into_owned());
710        }
711    }
712    None
713}
714
715/// assert 条件が `real_cond || !"message"` パターンかどうかを分解する
716fn decompose_assert_with_message(condition: &Expr) -> Option<(&Expr, String)> {
717    if let ExprKind::Binary { op: BinOp::LogOr, lhs, rhs } = &condition.kind {
718        if let Some(msg) = extract_assert_message(rhs) {
719            return Some((lhs, msg));
720        }
721    }
722    None
723}
724
725/// Perl の SV サブタイプ(GV, HV, AV, CV, IO 等)から SV へのポインタキャストかどうかを判定
726fn is_sv_subtype_cast(from: &UnifiedType, to: &UnifiedType) -> bool {
727    // inner 型を取得 (Named 以外は "c_void" 扱いにして void ポインタ互換を
728    // 拾う)。`Pointer { inner: Void }` は to_rust_string で c_void になる。
729    let inner_name = |ut: &UnifiedType| -> Option<String> {
730        match ut.inner_type()? {
731            UnifiedType::Named(name) => Some(name.clone()),
732            UnifiedType::Void => Some("c_void".to_string()),
733            _ => None,
734        }
735    };
736    let from_name = match inner_name(from) {
737        Some(n) => n,
738        None => return false,
739    };
740    let to_name = match inner_name(to) {
741        Some(n) => n,
742        None => return false,
743    };
744    // SV サブタイプのリスト (bindings.rs の構造体名は小文字版を出すケースが
745    // 多い: `pub type SV = sv;` などの typedef エイリアス関係のため、両方を
746    // 対象にする)
747    const SV_SUBTYPES: &[&str] = &[
748        "GV", "HV", "AV", "CV", "IO", "p5rx", "REGEXP",
749        "gv", "hv", "av", "cv", "io", "regexp",
750    ];
751    let sv_like = |n: &str| n == "SV" || n == "sv";
752    // SV ↔ サブタイプ(双方向)
753    (SV_SUBTYPES.contains(&from_name.as_str()) && sv_like(&to_name))
754        || (sv_like(&from_name) && SV_SUBTYPES.contains(&to_name.as_str()))
755        // サブタイプ ↔ サブタイプ (GV → CV など)
756        || (SV_SUBTYPES.contains(&from_name.as_str())
757            && SV_SUBTYPES.contains(&to_name.as_str()))
758        // c_void ↔ 任意のポインタ
759        || to_name == "c_void"
760        || from_name == "c_void"
761}
762
763fn is_null_literal(expr: &Expr) -> bool {
764    match &expr.kind {
765        ExprKind::IntLit(0) => true,
766        ExprKind::Cast { expr: inner, .. } => is_null_literal(inner),
767        _ => false,
768    }
769}
770
771/// ポインタ型に対応する null ポインタ式を生成
772fn null_ptr_expr(return_type: &UnifiedType) -> String {
773    if return_type.is_const_pointer() {
774        "std::ptr::null()".to_string()
775    } else {
776        "std::ptr::null_mut()".to_string()
777    }
778}
779
780/// 型文字列を正規化して整数型なら canonical Rust primitive に変換
781fn normalize_integer_type(ty: &str) -> Option<&'static str> {
782    match ty {
783        "u8" | "U8" | "c_uchar" => Some("u8"),
784        "u16" | "U16" | "c_ushort" => Some("u16"),
785        "u32" | "U32" | "c_uint" => Some("u32"),
786        "u64" | "U64" | "UV" | "c_ulong" | "c_ulonglong"
787            | "PERL_UINTMAX_T" => Some("u64"),
788        "i8" | "I8" | "c_schar" | "c_char" => Some("i8"),
789        "i16" | "I16" | "c_short" => Some("i16"),
790        "i32" | "I32" | "c_int" => Some("i32"),
791        "i64" | "I64" | "IV" | "c_long" | "c_longlong" => Some("i64"),
792        "usize" | "STRLEN" => Some("usize"),
793        "isize" | "SSize_t" | "ssize_t" | "PADOFFSET" => Some("isize"),
794        // Perl 固有の整数 typedef。Stack_off_t は 5.32+ で I32、それ以前は
795        // IV (i64) 相当だが、bindings.rs の型に合わせて i32 として扱う。
796        "Stack_off_t" => Some("i32"),
797        _ => None,
798    }
799}
800
801/// 64-bit プラットフォームで i64/isize, u64/usize を同一視して比較
802fn integer_types_compatible(a: &str, b: &str) -> bool {
803    if a == b { return true; }
804    matches!((a, b),
805        ("i64", "isize") | ("isize", "i64") |
806        ("u64", "usize") | ("usize", "u64")
807    )
808}
809
810/// 整数型の幅ランク (昇格順序判定用)
811/// returns (is_signed, width_rank)
812fn integer_type_rank(ty: &str) -> Option<(bool, u8)> {
813    match normalize_integer_type(ty)? {
814        "u8" => Some((false, 1)), "i8" => Some((true, 1)),
815        "u16" => Some((false, 2)), "i16" => Some((true, 2)),
816        "u32" => Some((false, 4)), "i32" => Some((true, 4)),
817        "u64" => Some((false, 8)), "i64" => Some((true, 8)),
818        "usize" => Some((false, 8)), "isize" => Some((true, 8)),
819        _ => None,
820    }
821}
822
823/// 二項ビット演算で C の整数昇格に従い広い方の型を返す
824/// 同一正規化型なら None(キャスト不要)
825fn wider_integer_type(a: &str, b: &str) -> Option<&'static str> {
826    let na = normalize_integer_type(a)?;
827    let nb = normalize_integer_type(b)?;
828    if na == nb { return None; }
829    let (a_signed, a_rank) = integer_type_rank(a)?;
830    let (_b_signed, b_rank) = integer_type_rank(b)?;
831    if a_rank == b_rank {
832        // 同一幅: unsigned が勝つ (C規格 6.3.1.8)
833        Some(if a_signed { nb } else { na })
834    } else if a_rank > b_rank {
835        Some(na)
836    } else {
837        Some(nb)
838    }
839}
840
841/// 2 つのポインタ型の inner が Rust として「同じ型」か判定する
842/// (const/mut は無視)。
843///
844/// `*mut c_char` と `*mut i8`、`*const c_int` と `*const i32` のように、
845/// C 別名と Rust プリミティブの対応関係を吸収する。
846/// 二重ポインタ `**const T` vs `**mut T` にも再帰的に対応する。
847pub fn pointer_inner_compatible(a: &UnifiedType, b: &UnifiedType) -> bool {
848    let a_inner = match a { UnifiedType::Pointer { inner, .. } => inner.as_ref(), _ => return false };
849    let b_inner = match b { UnifiedType::Pointer { inner, .. } => inner.as_ref(), _ => return false };
850    type_inner_compatible(a_inner, b_inner)
851}
852
853/// `pointer_inner_compatible` の再帰ヘルパ。ポインタ以外の inner も扱える。
854fn type_inner_compatible(a: &UnifiedType, b: &UnifiedType) -> bool {
855    // 両方ポインタなら再帰
856    if a.is_pointer() && b.is_pointer() {
857        return pointer_inner_compatible(a, b);
858    }
859    // 整数型は normalize_integer_type で正規化して比較
860    let a_s = a.to_rust_string();
861    let b_s = b.to_rust_string();
862    if let (Some(na), Some(nb)) = (normalize_integer_type(&a_s), normalize_integer_type(&b_s)) {
863        return na == nb;
864    }
865    // void は双方で吸収
866    if a.is_void() && b.is_void() { return true; }
867    // それ以外は文字列一致で判定
868    a_s == b_s
869}
870
871/// 両方ポインタで、inner は compatible だが const/mut が違う場合に true。
872pub fn pointer_const_differs(a: &UnifiedType, b: &UnifiedType) -> bool {
873    if !(a.is_pointer() && b.is_pointer()) { return false; }
874    if a.is_const_pointer() == b.is_const_pointer() { return false; }
875    pointer_inner_compatible(a, b)
876}
877
878/// マクロ本体を走査し、`&mut param` や代入先として使用されるパラメータを検出する
879/// ポインタパラメータが *mut である必要があるかを判定する。
880/// callee_const_params: 呼び出し先マクロで *const に確定したパラメータ情報
881///   key = マクロ名(InternedStr), value = const パラメータの引数位置集合
882pub fn collect_must_mut_pointer_params(
883    parse_result: &ParseResult,
884    params: &[MacroParam],
885    callee_const_params: &HashMap<InternedStr, HashSet<usize>>,
886) -> HashSet<InternedStr> {
887    let param_names: HashSet<InternedStr> = params.iter().map(|p| p.name).collect();
888    let mut result = HashSet::new();
889    match parse_result {
890        ParseResult::Expression(expr) => {
891            collect_must_mut_from_expr(expr, &param_names, callee_const_params, &mut result);
892        }
893        ParseResult::Statement(items) => {
894            for item in items {
895                if let BlockItem::Stmt(stmt) = item {
896                    collect_must_mut_from_stmt(stmt, &param_names, callee_const_params, &mut result);
897                }
898            }
899        }
900        ParseResult::Unparseable(_) => {}
901    }
902    result
903}
904
905pub fn collect_must_mut_from_stmt(
906    stmt: &Stmt,
907    params: &HashSet<InternedStr>,
908    callee_const: &HashMap<InternedStr, HashSet<usize>>,
909    result: &mut HashSet<InternedStr>,
910) {
911    match stmt {
912        Stmt::Expr(Some(expr), _) | Stmt::Return(Some(expr), _) => {
913            collect_must_mut_from_expr(expr, params, callee_const, result);
914        }
915        Stmt::Compound(compound) => {
916            for item in &compound.items {
917                match item {
918                    BlockItem::Stmt(s) => collect_must_mut_from_stmt(s, params, callee_const, result),
919                    BlockItem::Decl(decl) => {
920                        for init_decl in &decl.declarators {
921                            if let Some(Initializer::Expr(init)) = &init_decl.init {
922                                collect_must_mut_from_expr(init, params, callee_const, result);
923                            }
924                        }
925                    }
926                }
927            }
928        }
929        Stmt::If { cond, then_stmt, else_stmt, .. } => {
930            collect_must_mut_from_expr(cond, params, callee_const, result);
931            collect_must_mut_from_stmt(then_stmt, params, callee_const, result);
932            if let Some(e) = else_stmt {
933                collect_must_mut_from_stmt(e, params, callee_const, result);
934            }
935        }
936        Stmt::While { cond, body, .. } | Stmt::DoWhile { cond, body, .. } => {
937            collect_must_mut_from_expr(cond, params, callee_const, result);
938            collect_must_mut_from_stmt(body, params, callee_const, result);
939        }
940        Stmt::For { init, cond, step, body, .. } => {
941            if let Some(ForInit::Expr(e)) = init { collect_must_mut_from_expr(e, params, callee_const, result); }
942            if let Some(e) = cond { collect_must_mut_from_expr(e, params, callee_const, result); }
943            if let Some(e) = step { collect_must_mut_from_expr(e, params, callee_const, result); }
944            collect_must_mut_from_stmt(body, params, callee_const, result);
945        }
946        Stmt::Switch { expr, body, .. } => {
947            collect_must_mut_from_expr(expr, params, callee_const, result);
948            collect_must_mut_from_stmt(body, params, callee_const, result);
949        }
950        _ => {}
951    }
952}
953
954pub fn collect_must_mut_from_expr(
955    expr: &Expr,
956    params: &HashSet<InternedStr>,
957    callee_const: &HashMap<InternedStr, HashSet<usize>>,
958    result: &mut HashSet<InternedStr>,
959) {
960    match &expr.kind {
961        // *param = expr, param->field = expr → param must be *mut
962        ExprKind::Assign { lhs, rhs, .. } => {
963            mark_lvalue_mut(lhs, params, result);
964            collect_must_mut_from_expr(lhs, params, callee_const, result);
965            collect_must_mut_from_expr(rhs, params, callee_const, result);
966        }
967        // ++(*param), (*param)++ 等
968        ExprKind::PreInc(inner) | ExprKind::PreDec(inner) |
969        ExprKind::PostInc(inner) | ExprKind::PostDec(inner) => {
970            mark_lvalue_mut(inner, params, result);
971            collect_must_mut_from_expr(inner, params, callee_const, result);
972        }
973        // func(param) — 呼び出し先の引数 mutability をチェック
974        ExprKind::Call { func, args } => {
975            // 呼び出し先マクロの const 情報をチェック
976            if let ExprKind::Ident(func_name) = &func.kind {
977                let const_arg_positions = callee_const.get(func_name);
978                for (i, arg) in args.iter().enumerate() {
979                    if let ExprKind::Ident(arg_name) = &arg.kind {
980                        if params.contains(arg_name) {
981                            // 呼び出し先の i 番目が const なら mut 不要
982                            let is_const_at_callee = const_arg_positions
983                                .map_or(false, |positions| positions.contains(&i));
984                            if !is_const_at_callee {
985                                // 呼び出し先が const でない(or 情報なし)→ mut 必要
986                                result.insert(*arg_name);
987                            }
988                        }
989                    }
990                    collect_must_mut_from_expr(arg, params, callee_const, result);
991                }
992            } else {
993                for arg in args {
994                    collect_must_mut_from_expr(arg, params, callee_const, result);
995                }
996            }
997            collect_must_mut_from_expr(func, params, callee_const, result);
998        }
999        // 再帰
1000        ExprKind::Binary { lhs, rhs, .. } | ExprKind::Comma { lhs, rhs } => {
1001            collect_must_mut_from_expr(lhs, params, callee_const, result);
1002            collect_must_mut_from_expr(rhs, params, callee_const, result);
1003        }
1004        ExprKind::Conditional { cond, then_expr, else_expr } => {
1005            collect_must_mut_from_expr(cond, params, callee_const, result);
1006            collect_must_mut_from_expr(then_expr, params, callee_const, result);
1007            collect_must_mut_from_expr(else_expr, params, callee_const, result);
1008        }
1009        // MacroCall(name, args) — 呼び出し先マクロの引数 mutability をチェック
1010        ExprKind::MacroCall { name, args, expanded, .. } => {
1011            let const_arg_positions = callee_const.get(name);
1012            for (i, arg) in args.iter().enumerate() {
1013                if let ExprKind::Ident(arg_name) = &arg.kind {
1014                    if params.contains(arg_name) {
1015                        let is_const_at_callee = const_arg_positions
1016                            .map_or(false, |positions| positions.contains(&i));
1017                        if !is_const_at_callee {
1018                            result.insert(*arg_name);
1019                        }
1020                    }
1021                }
1022                collect_must_mut_from_expr(arg, params, callee_const, result);
1023            }
1024            collect_must_mut_from_expr(expanded, params, callee_const, result);
1025        }
1026        ExprKind::Deref(inner) | ExprKind::UnaryMinus(inner) | ExprKind::BitNot(inner) |
1027        ExprKind::LogNot(inner) | ExprKind::AddrOf(inner) |
1028        ExprKind::Cast { expr: inner, .. } => {
1029            collect_must_mut_from_expr(inner, params, callee_const, result);
1030        }
1031        ExprKind::Member { expr: inner, .. } | ExprKind::PtrMember { expr: inner, .. } => {
1032            collect_must_mut_from_expr(inner, params, callee_const, result);
1033        }
1034        ExprKind::Sizeof(inner) => {
1035            collect_must_mut_from_expr(inner, params, callee_const, result);
1036        }
1037        ExprKind::Assert { condition, .. } => {
1038            collect_must_mut_from_expr(condition, params, callee_const, result);
1039        }
1040        ExprKind::StmtExpr(compound) => {
1041            for item in &compound.items {
1042                match item {
1043                    BlockItem::Stmt(s) => collect_must_mut_from_stmt(s, params, callee_const, result),
1044                    BlockItem::Decl(decl) => {
1045                        for init_decl in &decl.declarators {
1046                            if let Some(Initializer::Expr(init)) = &init_decl.init {
1047                                collect_must_mut_from_expr(init, params, callee_const, result);
1048                            }
1049                        }
1050                    }
1051                }
1052            }
1053        }
1054        _ => {}
1055    }
1056}
1057
1058/// 代入先の式に含まれるパラメータを must-mut としてマークする
1059pub fn mark_lvalue_mut(expr: &Expr, params: &HashSet<InternedStr>, result: &mut HashSet<InternedStr>) {
1060    match &expr.kind {
1061        // *param = ... → param must be *mut
1062        ExprKind::Deref(inner) => {
1063            if let ExprKind::Ident(name) = &inner.kind {
1064                if params.contains(name) {
1065                    result.insert(*name);
1066                }
1067            }
1068            // (*param).field の場合も再帰的にチェック
1069            mark_lvalue_mut(inner, params, result);
1070        }
1071        // param->field = ... → param must be *mut
1072        ExprKind::PtrMember { expr: inner, .. } => {
1073            if let ExprKind::Ident(name) = &inner.kind {
1074                if params.contains(name) {
1075                    result.insert(*name);
1076                }
1077            }
1078            mark_lvalue_mut(inner, params, result);
1079        }
1080        // (*param).field = ... → param must be *mut
1081        ExprKind::Member { expr: inner, .. } => {
1082            mark_lvalue_mut(inner, params, result);
1083        }
1084        // (SomeType*)param → キャスト先が *mut ならパラメータも mut
1085        ExprKind::Cast { expr: inner, type_name } => {
1086            if let ExprKind::Ident(name) = &inner.kind {
1087                if params.contains(name) {
1088                    // キャスト先がポインタで non-const なら mut 必要
1089                    let has_non_const_ptr = type_name.declarator.as_ref()
1090                        .map(|d| d.derived.iter().any(|dd| {
1091                            matches!(dd, crate::ast::DerivedDecl::Pointer(q) if !q.is_const)
1092                        }))
1093                        .unwrap_or(false);
1094                    if has_non_const_ptr {
1095                        result.insert(*name);
1096                    }
1097                }
1098            }
1099            mark_lvalue_mut(inner, params, result);
1100        }
1101        // MacroCall(name, expanded) → expanded 形式で lvalue を再帰チェック
1102        ExprKind::MacroCall { expanded, args, .. } => {
1103            mark_lvalue_mut(expanded, params, result);
1104            // 引数にパラメータが直接渡されている場合もチェック
1105            for arg in args {
1106                mark_lvalue_mut(arg, params, result);
1107            }
1108        }
1109        // Call の lvalue 使用: func(param) が lvalue として使われる場合
1110        // マクロ関数の呼び出し結果が lvalue なら、引数パラメータは *mut 必要
1111        ExprKind::Call { args, .. } => {
1112            for arg in args {
1113                if let ExprKind::Ident(name) = &arg.kind {
1114                    if params.contains(name) {
1115                        result.insert(*name);
1116                    }
1117                }
1118                mark_lvalue_mut(arg, params, result);
1119            }
1120        }
1121        _ => {}
1122    }
1123}
1124
1125fn collect_mut_params(parse_result: &ParseResult, params: &[MacroParam]) -> HashSet<InternedStr> {
1126    let param_names: HashSet<InternedStr> = params.iter().map(|p| p.name).collect();
1127    let mut result = HashSet::new();
1128    match parse_result {
1129        ParseResult::Expression(expr) => collect_mut_params_from_expr(expr, &param_names, &mut result),
1130        ParseResult::Statement(items) => {
1131            for item in items {
1132                if let BlockItem::Stmt(stmt) = item {
1133                    collect_mut_params_from_stmt(stmt, &param_names, &mut result);
1134                }
1135            }
1136        }
1137        ParseResult::Unparseable(_) => {}
1138    }
1139    result
1140}
1141
1142fn collect_mut_params_from_expr(expr: &Expr, params: &HashSet<InternedStr>, result: &mut HashSet<InternedStr>) {
1143    match &expr.kind {
1144        ExprKind::AddrOf(inner) => {
1145            // &mut param → param needs mut
1146            if let ExprKind::Ident(name) = &inner.kind {
1147                if params.contains(name) {
1148                    result.insert(*name);
1149                }
1150            }
1151            collect_mut_params_from_expr(inner, params, result);
1152        }
1153        ExprKind::Assign { lhs, rhs, .. } => {
1154            // param = ... or param += ... → param needs mut
1155            if let ExprKind::Ident(name) = &lhs.kind {
1156                if params.contains(name) {
1157                    result.insert(*name);
1158                }
1159            }
1160            collect_mut_params_from_expr(lhs, params, result);
1161            collect_mut_params_from_expr(rhs, params, result);
1162        }
1163        ExprKind::PreInc(inner) | ExprKind::PreDec(inner) |
1164        ExprKind::PostInc(inner) | ExprKind::PostDec(inner) => {
1165            if let ExprKind::Ident(name) = &inner.kind {
1166                if params.contains(name) {
1167                    result.insert(*name);
1168                }
1169            }
1170            collect_mut_params_from_expr(inner, params, result);
1171        }
1172        // Recurse into subexpressions
1173        ExprKind::Binary { lhs, rhs, .. } => {
1174            collect_mut_params_from_expr(lhs, params, result);
1175            collect_mut_params_from_expr(rhs, params, result);
1176        }
1177        ExprKind::Deref(inner) | ExprKind::UnaryMinus(inner) | ExprKind::BitNot(inner) |
1178        ExprKind::LogNot(inner) | ExprKind::Cast { expr: inner, .. } => {
1179            collect_mut_params_from_expr(inner, params, result);
1180        }
1181        ExprKind::Call { func, args } => {
1182            collect_mut_params_from_expr(func, params, result);
1183            for arg in args {
1184                collect_mut_params_from_expr(arg, params, result);
1185            }
1186        }
1187        ExprKind::MacroCall { expanded, args, .. } => {
1188            collect_mut_params_from_expr(expanded, params, result);
1189            for arg in args {
1190                collect_mut_params_from_expr(arg, params, result);
1191            }
1192        }
1193        ExprKind::Conditional { cond, then_expr, else_expr } => {
1194            collect_mut_params_from_expr(cond, params, result);
1195            collect_mut_params_from_expr(then_expr, params, result);
1196            collect_mut_params_from_expr(else_expr, params, result);
1197        }
1198        ExprKind::Comma { lhs, rhs } => {
1199            collect_mut_params_from_expr(lhs, params, result);
1200            collect_mut_params_from_expr(rhs, params, result);
1201        }
1202        ExprKind::Member { expr: inner, .. } | ExprKind::PtrMember { expr: inner, .. } => {
1203            collect_mut_params_from_expr(inner, params, result);
1204        }
1205        ExprKind::StmtExpr(compound) => {
1206            for item in &compound.items {
1207                if let BlockItem::Stmt(stmt) = item {
1208                    collect_mut_params_from_stmt(stmt, params, result);
1209                }
1210            }
1211        }
1212        _ => {}
1213    }
1214}
1215
1216fn collect_mut_params_from_stmt(stmt: &Stmt, params: &HashSet<InternedStr>, result: &mut HashSet<InternedStr>) {
1217    match stmt {
1218        Stmt::Expr(Some(expr), _) => collect_mut_params_from_expr(expr, params, result),
1219        Stmt::Return(Some(expr), _) => collect_mut_params_from_expr(expr, params, result),
1220        Stmt::If { cond, then_stmt, else_stmt, .. } => {
1221            collect_mut_params_from_expr(cond, params, result);
1222            collect_mut_params_from_stmt(then_stmt, params, result);
1223            if let Some(else_s) = else_stmt {
1224                collect_mut_params_from_stmt(else_s, params, result);
1225            }
1226        }
1227        Stmt::Compound(compound) => {
1228            for item in &compound.items {
1229                if let BlockItem::Stmt(s) = item {
1230                    collect_mut_params_from_stmt(s, params, result);
1231                }
1232            }
1233        }
1234        Stmt::While { cond, body, .. } | Stmt::DoWhile { body, cond, .. } => {
1235            collect_mut_params_from_expr(cond, params, result);
1236            collect_mut_params_from_stmt(body, params, result);
1237        }
1238        Stmt::For { init, cond, step, body, .. } => {
1239            if let Some(ForInit::Expr(e)) = init {
1240                collect_mut_params_from_expr(e, params, result);
1241            }
1242            if let Some(c) = cond {
1243                collect_mut_params_from_expr(c, params, result);
1244            }
1245            if let Some(s) = step {
1246                collect_mut_params_from_expr(s, params, result);
1247            }
1248            collect_mut_params_from_stmt(body, params, result);
1249        }
1250        _ => {}
1251    }
1252}
1253
1254/// 構造体フィールド名 → 型の逆引きマップを構築
1255/// 全構造体で同名フィールドの型が一致する場合のみ含む
1256/// 型文字列が関数ポインタ形式(裸 fn または `Option<...fn(...)>`)かを判定する。
1257///
1258/// `quote::ToTokens` 経由の出力は `fn (` のようにスペースが入ることがあるため、
1259/// `fn(` と `fn (` の両方を許容する。
1260fn type_str_is_fn_pointer(ty_str: &str) -> bool {
1261    ty_str.contains("fn(") || ty_str.contains("fn (")
1262}
1263
1264fn build_field_type_map(dict: Option<&RustDeclDict>) -> HashMap<String, UnifiedType> {
1265    let mut map: HashMap<String, UnifiedType> = HashMap::new();
1266    let mut conflicts: HashSet<String> = HashSet::new();
1267    if let Some(dict) = dict {
1268        for st in dict.structs.values() {
1269            for field in &st.fields {
1270                if conflicts.contains(&field.name) {
1271                    continue;
1272                }
1273                match map.entry(field.name.clone()) {
1274                    std::collections::hash_map::Entry::Vacant(e) => {
1275                        e.insert(field.uty.clone());
1276                    }
1277                    std::collections::hash_map::Entry::Occupied(e) => {
1278                        if e.get() != &field.uty {
1279                            conflicts.insert(field.name.clone());
1280                            e.remove();
1281                        }
1282                    }
1283                }
1284            }
1285        }
1286        // bitfield アクセサ getter の戻り値型を統合。
1287        // C ソースの `(*o).op_type` (Member 式)は意味的に「op_type フィールド」
1288        // 相当だが、bindings.rs では bitfield アクセサ getter (`pub fn op_type(&self) -> U16`)
1289        // として現れる。型推論では同名のフィールドアクセスと同じ扱いで OK。
1290        for ((_struct, method), ret_ty) in &dict.bitfield_method_types {
1291            if conflicts.contains(method) {
1292                continue;
1293            }
1294            let uty = UnifiedType::from_rust_str(ret_ty);
1295            match map.entry(method.clone()) {
1296                std::collections::hash_map::Entry::Vacant(e) => {
1297                    e.insert(uty);
1298                }
1299                std::collections::hash_map::Entry::Occupied(e) => {
1300                    if e.get() != &uty {
1301                        conflicts.insert(method.clone());
1302                        e.remove();
1303                    }
1304                }
1305            }
1306        }
1307    }
1308    map
1309}
1310
1311/// コード生成の設定
1312#[derive(Debug, Clone)]
1313pub struct CodegenConfig {
1314    /// inline 関数を出力するか
1315    pub emit_inline_fns: bool,
1316    /// マクロを出力するか
1317    pub emit_macros: bool,
1318    /// コメントにソース位置を含めるか
1319    pub include_source_location: bool,
1320    /// ヘッダーに出力する use 文
1321    /// 空の場合はデフォルトの use 文を出力
1322    pub use_statements: Vec<String>,
1323    /// AST ダンプ対象関数名(デバッグ用)
1324    pub dump_ast_for: Option<String>,
1325    /// 型推論ダンプ対象関数名(デバッグ用)
1326    pub dump_types_for: Option<String>,
1327}
1328
1329impl Default for CodegenConfig {
1330    fn default() -> Self {
1331        Self {
1332            emit_inline_fns: true,
1333            emit_macros: true,
1334            include_source_location: true,
1335            use_statements: Vec::new(),
1336            dump_ast_for: None,
1337            dump_types_for: None,
1338        }
1339    }
1340}
1341
1342impl CodegenConfig {
1343    /// デフォルトの use 文を取得
1344    ///
1345    /// 生成コードで使用される C 型をインポートする。
1346    /// `size_t` などは Rust 組み込み型のエイリアスとして定義。
1347    pub fn default_use_statements() -> Vec<String> {
1348        vec![
1349            // 生成コードで実際に参照されない type alias / import が出ても
1350            // CI の `-D warnings` で落ちないよう dead_code / unused_imports を allow。
1351            "#[allow(unused_imports)] use std::ffi::{c_void, c_char, c_uchar, c_int, c_uint, c_long, c_ulong, c_short, c_ushort}".to_string(),
1352            "#[allow(non_camel_case_types, dead_code)] type size_t = usize".to_string(),
1353            "#[allow(non_camel_case_types, dead_code)] type ssize_t = isize".to_string(),
1354            "#[allow(non_camel_case_types, dead_code)] type SSize_t = isize".to_string(),
1355        ]
1356    }
1357
1358    /// use 文を設定
1359    pub fn with_use_statements(mut self, statements: Vec<String>) -> Self {
1360        self.use_statements = statements;
1361        self
1362    }
1363
1364    /// use 文を追加
1365    pub fn add_use_statement(mut self, statement: impl Into<String>) -> Self {
1366        self.use_statements.push(statement.into());
1367        self
1368    }
1369}
1370
1371/// 生成ステータス
1372#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1373pub enum GenerateStatus {
1374    /// 正常生成
1375    Success,
1376    /// パース失敗(S式をコメント出力)
1377    ParseFailed,
1378    /// 型推論不完全(型付S式をコメント出力)
1379    TypeIncomplete,
1380    /// 利用不可関数を呼び出す(コメント出力)
1381    CallsUnavailable,
1382    /// goto を含む(生成対象から除外)
1383    ContainsGoto,
1384    /// ジェネリクス型パラメータを含む(Rust の as T キャスト不可)
1385    GenericUnsupported,
1386    /// スキップ(対象外)
1387    Skip,
1388}
1389
1390/// 文が goto を含むか再帰的に検査
1391fn stmt_contains_goto(stmt: &Stmt) -> bool {
1392    match stmt {
1393        Stmt::Goto(_, _) => true,
1394        Stmt::Compound(cs) => block_items_contain_goto(&cs.items),
1395        Stmt::If { then_stmt, else_stmt, .. } => {
1396            stmt_contains_goto(then_stmt)
1397                || else_stmt.as_ref().is_some_and(|s| stmt_contains_goto(s))
1398        }
1399        Stmt::Switch { body, .. }
1400        | Stmt::While { body, .. }
1401        | Stmt::For { body, .. } => stmt_contains_goto(body),
1402        Stmt::DoWhile { body, .. } => stmt_contains_goto(body),
1403        Stmt::Label { stmt, .. } => stmt_contains_goto(stmt),
1404        Stmt::Case { stmt, .. } | Stmt::Default { stmt, .. } => stmt_contains_goto(stmt),
1405        _ => false,
1406    }
1407}
1408
1409/// ブロック項目リストが goto を含むか検査
1410fn block_items_contain_goto(items: &[BlockItem]) -> bool {
1411    items.iter().any(|item| match item {
1412        BlockItem::Stmt(stmt) => stmt_contains_goto(stmt),
1413        BlockItem::Decl(_) => false,
1414    })
1415}
1416
1417/// 文がトップレベルで `break;` を含むか検査
1418/// (ネストされた loop/switch 内の break は除外)。
1419fn stmt_contains_top_level_break(stmt: &Stmt) -> bool {
1420    match stmt {
1421        Stmt::Break(_) => true,
1422        Stmt::Compound(cs) => cs.items.iter().any(|item| match item {
1423            BlockItem::Stmt(s) => stmt_contains_top_level_break(s),
1424            BlockItem::Decl(_) => false,
1425        }),
1426        Stmt::If { then_stmt, else_stmt, .. } => {
1427            stmt_contains_top_level_break(then_stmt)
1428                || else_stmt.as_ref().is_some_and(|s| stmt_contains_top_level_break(s))
1429        }
1430        Stmt::Label { stmt, .. } => stmt_contains_top_level_break(stmt),
1431        // ネストした loop/switch 内の break は「外側ループ」に関係ないので
1432        // 再帰しない
1433        _ => false,
1434    }
1435}
1436
1437/// コード生成統計
1438#[derive(Debug, Clone, Default)]
1439pub struct CodegenStats {
1440    /// 正常生成されたマクロ数
1441    pub macros_success: usize,
1442    /// パース失敗マクロ数
1443    pub macros_parse_failed: usize,
1444    /// 型推論失敗マクロ数
1445    pub macros_type_incomplete: usize,
1446    /// 利用不可関数呼び出しマクロ数
1447    pub macros_calls_unavailable: usize,
1448    /// カスケード依存でコメントアウトされたマクロ数
1449    pub macros_cascade_unavailable: usize,
1450    /// ジェネリクス未対応マクロ数
1451    pub macros_generic_unsupported: usize,
1452    /// 未解決シンボルを含むマクロ数
1453    pub macros_unresolved_names: usize,
1454    /// 正常生成された inline 関数数
1455    pub inline_fns_success: usize,
1456    /// 型推論失敗 inline 関数数
1457    pub inline_fns_type_incomplete: usize,
1458    /// 未解決シンボルを含む inline 関数数
1459    pub inline_fns_unresolved_names: usize,
1460    /// カスケード依存でコメントアウトされた inline 関数数
1461    pub inline_fns_cascade_unavailable: usize,
1462    /// goto を含む inline 関数数
1463    pub inline_fns_contains_goto: usize,
1464}
1465
1466/// codegen の関数別結果。emit された名前と、されなかった名前 → 理由。
1467///
1468/// `CodegenDriver` が出力 (Pass 3) の各マーカー分岐で記録する。
1469/// `--require-codegen-list` の検証 (`check_required`) に使う。
1470/// BTree 系なのは違反レポートの列挙順を決定化するため。
1471#[derive(Debug, Clone, Default)]
1472pub struct CodegenReport {
1473    /// 実関数として emit された名前
1474    pub emitted: BTreeSet<String>,
1475    /// emit されなかった名前 → 理由 (マーカー種別 + 詳細)
1476    pub skipped: BTreeMap<String, String>,
1477}
1478
1479impl CodegenReport {
1480    fn record_emit(&mut self, name: impl Into<String>) {
1481        self.emitted.insert(name.into());
1482    }
1483
1484    fn record_skip(&mut self, name: impl Into<String>, reason: impl Into<String>) {
1485        self.skipped.insert(name.into(), reason.into());
1486    }
1487
1488    /// required のうち emit されなかったものを理由付きで返す。
1489    /// 全て emit 済みなら Ok。emitted にも skipped にも無い名前は
1490    /// codegen 対象に現れなかったもの (apidoc 宣言なし、ヘッダに定義なし等)。
1491    pub fn check_required(&self, required: &[String]) -> Result<(), RequireCodegenError> {
1492        let mut violations = Vec::new();
1493        for name in required {
1494            if self.emitted.contains(name) {
1495                continue;
1496            }
1497            let reason = match self.skipped.get(name) {
1498                Some(r) => r.clone(),
1499                None => "not a codegen target (no apidoc declaration or not defined in headers)"
1500                    .to_string(),
1501            };
1502            violations.push(RequireViolation {
1503                name: name.clone(),
1504                reason,
1505            });
1506        }
1507        if violations.is_empty() {
1508            Ok(())
1509        } else {
1510            Err(RequireCodegenError { violations })
1511        }
1512    }
1513}
1514
1515/// `--require-codegen-list` 違反 (必須名が emit されなかった)
1516#[derive(Debug, Clone)]
1517pub struct RequireCodegenError {
1518    pub violations: Vec<RequireViolation>,
1519}
1520
1521/// 1 件の違反: 名前と、emit されなかった理由
1522#[derive(Debug, Clone)]
1523pub struct RequireViolation {
1524    pub name: String,
1525    pub reason: String,
1526}
1527
1528impl std::fmt::Display for RequireCodegenError {
1529    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1530        writeln!(
1531            f,
1532            "require-codegen-list violation: {} function(s) not generated:",
1533            self.violations.len()
1534        )?;
1535        for v in &self.violations {
1536            writeln!(f, "  {} - {}", v.name, v.reason)?;
1537        }
1538        Ok(())
1539    }
1540}
1541
1542impl std::error::Error for RequireCodegenError {}
1543
1544/// 一つの関数の生成結果
1545#[derive(Debug, Clone)]
1546pub struct GeneratedCode {
1547    /// 生成されたコード
1548    pub code: String,
1549    /// 不完全マーカーの数
1550    pub incomplete_count: usize,
1551    /// 検出された未解決シンボル名(重複なし、出現順)
1552    pub unresolved_names: Vec<String>,
1553    /// 使用された libc 関数名
1554    pub used_libc_fns: HashSet<String>,
1555    /// codegen で検出されたエラー(コメントアウトの理由)
1556    pub codegen_errors: Vec<String>,
1557}
1558
1559impl GeneratedCode {
1560    /// 生成が完全かどうか(不完全マーカーがないか)
1561    pub fn is_complete(&self) -> bool {
1562        self.incomplete_count == 0
1563    }
1564
1565    /// 未解決シンボルがあるかどうか
1566    pub fn has_unresolved_names(&self) -> bool {
1567        !self.unresolved_names.is_empty()
1568    }
1569}
1570
1571/// 単一関数を生成するためのコード生成器(使い捨て)
1572///
1573/// 各関数の生成ごとにフレッシュなインスタンスを作成して使用する。
1574/// 生成中に不完全マーカーが出力された回数をカウントし、
1575/// 生成完了時に `GeneratedCode` として結果を返す。
1576pub struct RustCodegen<'a> {
1577    interner: &'a StringInterner,
1578    /// Enum バリアント辞書(パターンマッチ用)
1579    enum_dict: &'a EnumDict,
1580    /// マクロ推論コンテキスト(THX マクロ呼び出し判定用)
1581    macro_ctx: &'a MacroInferContext,
1582    /// bindings.rs から抽出した情報
1583    bindings_info: BindingsInfo,
1584    /// 内部バッファ(生成結果を蓄積)
1585    buffer: String,
1586    /// 不完全マーカーの生成回数
1587    incomplete_count: usize,
1588    /// 現在生成中のマクロの型パラメータマップ
1589    /// 仮引数名(InternedStr) → ジェネリック名("T", "U", ...)
1590    current_type_param_map: HashMap<InternedStr, String>,
1591    /// 現在生成中のマクロのリテラル文字列パラメータ名の集合
1592    current_literal_string_params: HashSet<InternedStr>,
1593    /// 現在生成中の関数の戻り値型
1594    current_return_type: Option<UnifiedType>,
1595    /// Call式のlvalue展開時に使用するパラメータ置換テーブル
1596    /// マクロ仮引数名 → 実引数のRust文字列
1597    param_substitutions: HashMap<InternedStr, String>,
1598    /// 現在生成中の関数のパラメータ型情報
1599    /// パラメータ名 → 型
1600    current_param_types: HashMap<InternedStr, UnifiedType>,
1601    /// 既知シンボル集合への参照(未解決シンボル検出用)
1602    known_symbols: &'a KnownSymbols,
1603    /// 現在の関数のローカルスコープ(パラメータ名 + ローカル変数名)
1604    current_local_names: HashSet<InternedStr>,
1605    /// 検出された未解決シンボル名(重複なし、出現順)
1606    unresolved_names: Vec<String>,
1607    /// 使用された libc 関数名
1608    used_libc_fns: HashSet<String>,
1609    /// Rust 宣言辞書への参照(関数パラメータ型参照用)
1610    rust_decl_dict: Option<&'a RustDeclDict>,
1611    /// inline 関数辞書への参照(戻り値型/引数型判定用)
1612    inline_fn_dict: Option<&'a crate::inline_fn::InlineFnDict>,
1613    /// FieldsDict への参照(共通フィールドマクロの canonical type 参照用)
1614    fields_dict: Option<&'a crate::fields_dict::FieldsDict>,
1615    /// 構造体フィールド名 → 型の逆引きマップ
1616    field_type_map: HashMap<String, UnifiedType>,
1617    /// AST ダンプ対象関数名(デバッグ用)
1618    dump_ast_for: Option<String>,
1619    /// 型推論ダンプ対象関数名(デバッグ用)
1620    dump_types_for: Option<String>,
1621    /// const ポインタに変換可能なパラメータの引数位置集合
1622    const_pointer_positions: HashSet<usize>,
1623    /// 再代入されるローカル変数名の集合(let mut 判定用)
1624    mut_local_names: HashSet<InternedStr>,
1625    /// codegen で検出されたエラー
1626    codegen_errors: Vec<String>,
1627    /// このマクロが bool を返すと判定されたか
1628    is_bool_return: bool,
1629    /// codegen で bool を返すと判定されたマクロの集合(呼び出し先の bool 判定用)
1630    bool_return_macros: HashSet<InternedStr>,
1631    /// 対象 perl が threaded build か(false なら my_perl 注入を抑止)
1632    perl_threaded: bool,
1633}
1634
1635/// コード生成全体を管理する構造体
1636///
1637/// 実際の出力先(Write)を保持し、生成の成功/失敗に応じて
1638/// 適切な形式で出力する。
1639pub struct CodegenDriver<'a, W: Write> {
1640    writer: W,
1641    interner: &'a StringInterner,
1642    /// Enum バリアント辞書(パターンマッチ用)
1643    enum_dict: &'a EnumDict,
1644    /// マクロ推論コンテキスト(THX マクロ呼び出し判定用)
1645    macro_ctx: &'a MacroInferContext,
1646    /// bindings.rs から抽出した情報
1647    bindings_info: BindingsInfo,
1648    config: CodegenConfig,
1649    stats: CodegenStats,
1650    /// 関数別の生成結果 (--require-codegen-list 検証用)
1651    report: CodegenReport,
1652    /// 生成されたコード全体で使用された libc 関数名
1653    used_libc_fns: HashSet<String>,
1654    /// 正常生成された inline 関数名(クロスドメインカスケード検出用)
1655    successfully_generated_inlines: HashSet<InternedStr>,
1656    /// 生成可能と予測されるマクロの集合(inline→macro カスケード検出用)
1657    generatable_macros: HashSet<InternedStr>,
1658    /// const ポインタに変換可能なマクロパラメータ: マクロ名 → const パラメータの引数位置集合
1659    const_pointer_params: HashMap<InternedStr, HashSet<usize>>,
1660    /// bool を返すと判定されたマクロの集合
1661    bool_return_macros: HashSet<InternedStr>,
1662    /// 対象 perl が threaded build か(false なら my_perl 注入を抑止)
1663    perl_threaded: bool,
1664}
1665
1666impl<'a> RustCodegen<'a> {
1667    /// 新しい単一関数用コード生成器を作成
1668    pub fn new(
1669        interner: &'a StringInterner,
1670        enum_dict: &'a EnumDict,
1671        macro_ctx: &'a MacroInferContext,
1672        bindings_info: BindingsInfo,
1673        known_symbols: &'a KnownSymbols,
1674        rust_decl_dict: Option<&'a RustDeclDict>,
1675        inline_fn_dict: Option<&'a crate::inline_fn::InlineFnDict>,
1676    ) -> Self {
1677        Self {
1678            interner,
1679            enum_dict,
1680            macro_ctx,
1681            bindings_info,
1682            buffer: String::new(),
1683            incomplete_count: 0,
1684            current_type_param_map: HashMap::new(),
1685            current_literal_string_params: HashSet::new(),
1686            current_return_type: None,
1687            param_substitutions: HashMap::new(),
1688            current_param_types: HashMap::new(),
1689            known_symbols,
1690            current_local_names: HashSet::new(),
1691            unresolved_names: Vec::new(),
1692            used_libc_fns: HashSet::new(),
1693            rust_decl_dict,
1694            inline_fn_dict,
1695            fields_dict: None,
1696            field_type_map: build_field_type_map(rust_decl_dict),
1697            dump_ast_for: None,
1698            dump_types_for: None,
1699            const_pointer_positions: HashSet::new(),
1700            is_bool_return: false,
1701            bool_return_macros: HashSet::new(),
1702            mut_local_names: HashSet::new(),
1703            codegen_errors: Vec::new(),
1704            // デフォルトは threaded(後方互換)。Driver 経由で
1705            // with_perl_threaded() で上書きされる。
1706            perl_threaded: true,
1707        }
1708    }
1709
1710    /// 対象 perl が threaded かを設定
1711    pub fn with_perl_threaded(mut self, threaded: bool) -> Self {
1712        self.perl_threaded = threaded;
1713        self
1714    }
1715
1716    /// AST ダンプ対象関数名を設定(デバッグ用)
1717    pub fn with_dump_ast_for(mut self, name: Option<String>) -> Self {
1718        self.dump_ast_for = name;
1719        self
1720    }
1721
1722    pub fn with_dump_types_for(mut self, name: Option<String>) -> Self {
1723        self.dump_types_for = name;
1724        self
1725    }
1726
1727    /// FieldsDict への参照を設定
1728    pub fn with_fields_dict(mut self, dict: &'a crate::fields_dict::FieldsDict) -> Self {
1729        self.fields_dict = Some(dict);
1730        // bindings.rs に無い自動生成 struct (body_details 等) の
1731        // フィールド型を field_type_map にマージし、Member 式の型推論で
1732        // 利用できるようにする。bindings.rs 側で既に登録されている
1733        // フィールドは優先する。
1734        for (_name, def) in dict.iter_struct_defs() {
1735            for m in &def.members {
1736                let member_name = self.interner.get(m.name).to_string();
1737                if self.field_type_map.contains_key(&member_name) {
1738                    continue;
1739                }
1740                let rust_ty = m.type_repr.to_rust_string(self.interner);
1741                self.field_type_map
1742                    .insert(member_name, UnifiedType::from_rust_str(&rust_ty));
1743            }
1744        }
1745        self
1746    }
1747
1748    /// const ポインタ位置を設定
1749    pub fn with_const_pointer_positions(mut self, positions: HashSet<usize>) -> Self {
1750        self.const_pointer_positions = positions;
1751        self
1752    }
1753
1754    /// bool 戻り値フラグと bool マクロ集合を設定
1755    pub fn with_bool_return(mut self, is_bool: bool, bool_macros: HashSet<InternedStr>) -> Self {
1756        self.is_bool_return = is_bool;
1757        self.bool_return_macros = bool_macros;
1758        self
1759    }
1760
1761    /// 指定された関数名が AST ダンプ対象かどうかを判定し、対象なら AST をコメントとして出力
1762    /// 型推論結果を stderr にダンプ(デバッグ用)
1763    fn dump_type_info(&self, name_str: &str, info: &MacroInferInfo, params_str: &str, return_type: &str) {
1764        eprintln!("=== Type dump for {} ===", name_str);
1765        // パラメータ型
1766        for (i, p) in info.params.iter().enumerate() {
1767            let pname = self.interner.get(p.name);
1768            let is_const = info.const_pointer_positions.contains(&i);
1769            // 全制約を表示
1770            let expr_ids: Vec<_> = info.type_env.param_to_exprs
1771                .get(&p.name)
1772                .map(|ids| ids.iter().cloned().collect())
1773                .unwrap_or_default();
1774            let mut all_ids = expr_ids;
1775            all_ids.push(p.expr_id());
1776            eprintln!("  param[{}] {} (const_position={})", i, pname, is_const);
1777            for eid in &all_ids {
1778                if let Some(constraints) = info.type_env.expr_constraints.get(eid) {
1779                    for c in constraints {
1780                        eprintln!("    constraint: tier={} rust={} context={} source={:?}",
1781                            c.ty.confidence_tier(),
1782                            c.ty.to_rust_string(self.interner),
1783                            c.context,
1784                            match &c.ty {
1785                                crate::type_repr::TypeRepr::CType { source, .. } => format!("{:?}", source),
1786                                crate::type_repr::TypeRepr::RustType { source, .. } => format!("{:?}", source),
1787                                crate::type_repr::TypeRepr::Inferred(i) => format!("Inferred({:?})", std::mem::discriminant(i)),
1788                            }
1789                        );
1790                    }
1791                }
1792            }
1793        }
1794        eprintln!("  params_str: {}", params_str);
1795        // 戻り値型
1796        eprintln!("  return_type: {}", return_type);
1797        eprintln!("  is_bool_return: {}", info.is_bool_return);
1798        if let Some(ty) = info.get_return_type() {
1799            eprintln!("  return TypeRepr: tier={} rust={}", ty.confidence_tier(), ty.to_rust_string(self.interner));
1800        }
1801        // return_constraints (apidoc 由来)
1802        if !info.type_env.return_constraints.is_empty() {
1803            eprintln!("  return_constraints:");
1804            for c in &info.type_env.return_constraints {
1805                eprintln!("    tier={} rust={} context={}", c.ty.confidence_tier(), c.ty.to_rust_string(self.interner), c.context);
1806            }
1807        }
1808        // ルート式の全制約
1809        if let ParseResult::Expression(ref expr) = info.parse_result {
1810            if let Some(constraints) = info.type_env.expr_constraints.get(&expr.id) {
1811                eprintln!("  root expr constraints:");
1812                for c in constraints {
1813                    eprintln!("    tier={} rust={} context={}",
1814                        c.ty.confidence_tier(),
1815                        c.ty.to_rust_string(self.interner),
1816                        c.context,
1817                    );
1818                }
1819            }
1820        }
1821        eprintln!("=== End type dump ===");
1822    }
1823
1824    fn dump_ast_comment_for_expr(&mut self, name_str: &str, parse_result: &ParseResult) {
1825        if self.dump_ast_for.as_deref() != Some(name_str) {
1826            return;
1827        }
1828        let sexp = match parse_result {
1829            ParseResult::Expression(expr) => {
1830                let mut buf = Vec::new();
1831                let mut printer = SexpPrinter::new(&mut buf, self.interner);
1832                let _ = printer.print_expr(expr);
1833                String::from_utf8_lossy(&buf).into_owned()
1834            }
1835            ParseResult::Statement(block_items) => {
1836                let mut buf = Vec::new();
1837                let mut printer = SexpPrinter::new(&mut buf, self.interner);
1838                for item in block_items {
1839                    if let BlockItem::Stmt(stmt) = item {
1840                        let _ = printer.print_stmt(stmt);
1841                    } else if let BlockItem::Decl(decl) = item {
1842                        let _ = printer.print_declaration(decl);
1843                    }
1844                }
1845                String::from_utf8_lossy(&buf).into_owned()
1846            }
1847            ParseResult::Unparseable(msg) => {
1848                format!("(unparseable: {})", msg.as_deref().unwrap_or("unknown"))
1849            }
1850        };
1851        self.writeln(&format!("// [AST dump for {}]", name_str));
1852        for line in sexp.lines() {
1853            self.writeln(&format!("// {}", line));
1854        }
1855    }
1856
1857    /// 指定された関数名が AST ダンプ対象かどうかを判定し、対象なら CompoundStmt をコメントとして出力
1858    fn dump_ast_comment_for_body(&mut self, name_str: &str, body: &CompoundStmt) {
1859        if self.dump_ast_for.as_deref() != Some(name_str) {
1860            return;
1861        }
1862        let mut buf = Vec::new();
1863        let mut printer = SexpPrinter::new(&mut buf, self.interner);
1864        for item in &body.items {
1865            match item {
1866                BlockItem::Stmt(stmt) => { let _ = printer.print_stmt(stmt); }
1867                BlockItem::Decl(decl) => { let _ = printer.print_declaration(decl); }
1868            }
1869        }
1870        let sexp = String::from_utf8_lossy(&buf).into_owned();
1871        self.writeln(&format!("// [AST dump for {}]", name_str));
1872        for line in sexp.lines() {
1873            self.writeln(&format!("// {}", line));
1874        }
1875    }
1876
1877    /// Call 式が lvalue マクロ呼び出しなら、展開済み lvalue を syn::Expr で返す。
1878    /// パラメータ置換マップは依然 `String` だが、本体の AST 走査は
1879    /// `build_syn_expr` を経由するため `expr_to_rust*` への依存はない。
1880    fn try_expand_call_as_lvalue_syn(&mut self, func: &Expr, args: &[Expr],
1881                                     info: Option<&MacroInferInfo>) -> Option<syn::Expr> {
1882        if let ExprKind::Ident(name) = &func.kind {
1883            if self.should_emit_as_macro_call(*name) {
1884                if let Some(macro_info) = self.macro_ctx.macros.get(name) {
1885                    if let ParseResult::Expression(body) = &macro_info.parse_result {
1886                        let body = body.clone();
1887                        let saved_params = std::mem::take(&mut self.param_substitutions);
1888                        for (i, param) in macro_info.params.iter().enumerate() {
1889                            if let Some(arg) = args.get(i) {
1890                                let arg_syn = self.build_syn_expr(arg, info);
1891                                let arg_str = crate::syn_codegen::expr_to_string(&arg_syn);
1892                                self.param_substitutions.insert(param.name, arg_str);
1893                            }
1894                        }
1895                        let body_syn = self.build_syn_expr(&body, info);
1896                        self.param_substitutions = saved_params;
1897                        return Some(body_syn);
1898                    }
1899                }
1900            }
1901        }
1902        None
1903    }
1904
1905
1906    /// ポインタ式をbool条件に変換するラッパー(inline関数用)— 統一版に委譲
1907    fn wrap_as_bool_condition_inline(&self, expr: &Expr, expr_str: &str) -> String {
1908        self.wrap_as_bool_condition(expr, expr_str, None)
1909    }
1910
1911    /// 式の型を推定(inline 関数用)— 統一版に委譲
1912    fn infer_expr_type_inline(&self, expr: &Expr) -> Option<UnifiedType> {
1913        self.infer_expr_type_unified(expr, None)
1914    }
1915
1916    /// TypeName から型文字列を取得(読み取り専用、整数型を正しく解決する版)
1917    fn type_name_to_type_str_readonly(&self, type_name: &crate::ast::TypeName) -> String {
1918        // ポインタの個数をカウント
1919        let pointer_count = type_name.declarator.as_ref()
1920            .map(|d| d.derived.iter().filter(|dd| matches!(dd, crate::ast::DerivedDecl::Pointer(_))).count())
1921            .unwrap_or(0);
1922        // const チェック:
1923        // C の "const T *p" → pointee は const → Rust: *const T
1924        //   この場合 const は specs.qualifiers.is_const にある
1925        // C の "T * const p" → ポインタ自体が const (再代入不可) → Rust: *mut T
1926        //   こ���場合 const は Pointer(qualifiers.is_const) にある → Rust の *const ではない
1927        let is_const_ptr = pointer_count == 1 && type_name.specs.qualifiers.is_const;
1928        // 基本型を取得
1929        let base = self.base_type_str_readonly(&type_name.specs.type_specs);
1930        // ポインタをラップ
1931        let mut result = base;
1932        for _ in 0..pointer_count {
1933            let prefix = if is_const_ptr { "*const " } else { "*mut " };
1934            result = format!("{}{}", prefix, result);
1935        }
1936        result
1937    }
1938
1939    /// TypeSpec リストから基本型名を取得する(読み取り専用)
1940    fn base_type_str_readonly(&self, type_specs: &[TypeSpec]) -> String {
1941        // typedef 名を優先
1942        for spec in type_specs {
1943            if let TypeSpec::TypedefName(name) = spec {
1944                return self.interner.get(*name).to_string();
1945            }
1946        }
1947        // struct/union/enum 名
1948        for spec in type_specs {
1949            match spec {
1950                TypeSpec::Struct(s) | TypeSpec::Union(s) => {
1951                    if let Some(n) = &s.name {
1952                        return self.interner.get(*n).to_string();
1953                    }
1954                }
1955                TypeSpec::Enum(e) => {
1956                    if let Some(n) = &e.name {
1957                        return self.interner.get(*n).to_string();
1958                    }
1959                }
1960                _ => {}
1961            }
1962        }
1963        let mut is_void = false;
1964        let mut is_char = false;
1965        let mut is_int = false;
1966        let mut is_short = false;
1967        let mut is_long = 0usize;
1968        let mut is_unsigned = false;
1969        for spec in type_specs {
1970            match spec {
1971                TypeSpec::Void => is_void = true,
1972                TypeSpec::Char => is_char = true,
1973                TypeSpec::Int => is_int = true,
1974                TypeSpec::Short => is_short = true,
1975                TypeSpec::Long => is_long += 1,
1976                TypeSpec::Unsigned => is_unsigned = true,
1977                TypeSpec::Signed => {}
1978                TypeSpec::Bool => return "bool".to_string(),
1979                _ => {}
1980            }
1981        }
1982        if is_void { return "c_void".to_string(); }
1983        if is_char { return if is_unsigned { "c_uchar".to_string() } else { "c_char".to_string() }; }
1984        if is_short { return if is_unsigned { "c_ushort".to_string() } else { "c_short".to_string() }; }
1985        if is_long >= 2 { return if is_unsigned { "c_ulonglong".to_string() } else { "c_longlong".to_string() }; }
1986        if is_long == 1 { return if is_unsigned { "c_ulong".to_string() } else { "c_long".to_string() }; }
1987        if is_int || is_unsigned { return if is_unsigned { "c_uint".to_string() } else { "c_int".to_string() }; }
1988        "c_int".to_string()
1989    }
1990
1991    /// 式の型を推定(macro 関数用)— 統一版に委譲
1992    fn infer_expr_type(&self, expr: &Expr, info: &MacroInferInfo) -> Option<UnifiedType> {
1993        self.infer_expr_type_unified(expr, Some(info))
1994    }
1995
1996    // ================================================================
1997    // 統一型推論 (macro/inline 共通)
1998    // ================================================================
1999
2000    /// 式の型を推定(macro/inline 統一版)
2001    ///
2002    /// `info` が Some の場合は TypeEnv (Tier ベース) も参照する(マクロ用)。
2003    /// None の場合は current_param_types のみ参照する(inline 用)。
2004    fn infer_expr_type_unified(&self, expr: &Expr, info: Option<&MacroInferInfo>) -> Option<UnifiedType> {
2005        match &expr.kind {
2006            ExprKind::Ident(name) => {
2007                // current_param_types を最優先(Tier ベースで決定済み)
2008                if let Some(ut) = self.current_param_types.get(name) {
2009                    return Some(ut.clone());
2010                }
2011                // TypeEnv 参照(マクロ用: Tier ベースで最良の制約を選択)
2012                if let Some(info) = info {
2013                    // param_to_exprs 経由の expr_constraints
2014                    if let Some(expr_ids) = info.type_env.param_to_exprs.get(name) {
2015                        let mut best: Option<(UnifiedType, u8)> = None;
2016                        for expr_id in expr_ids {
2017                            if let Some(constraints) = info.type_env.expr_constraints.get(expr_id) {
2018                                for c in constraints {
2019                                    if c.ty.is_void() { continue; }
2020                                    let tier = c.ty.confidence_tier();
2021                                    if best.is_none() || tier < best.as_ref().unwrap().1 {
2022                                        best = Some((UnifiedType::from_rust_str(&c.ty.to_rust_string(self.interner)), tier));
2023                                    }
2024                                }
2025                            }
2026                        }
2027                        if let Some((ut, _)) = best {
2028                            return Some(ut);
2029                        }
2030                    }
2031                    // param_constraints(フォールバック、Tier ベース)
2032                    if let Some(constraints) = info.type_env.param_constraints.get(name) {
2033                        let mut best: Option<(UnifiedType, u8)> = None;
2034                        for c in constraints {
2035                            if c.ty.is_void() { continue; }
2036                            let tier = c.ty.confidence_tier();
2037                            if best.is_none() || tier < best.as_ref().unwrap().1 {
2038                                best = Some((UnifiedType::from_rust_str(&c.ty.to_rust_string(self.interner)), tier));
2039                            }
2040                        }
2041                        if let Some((ut, _)) = best {
2042                            return Some(ut);
2043                        }
2044                    }
2045                }
2046                // 定数の型
2047                if let Some(dict) = self.rust_decl_dict {
2048                    let name_str = self.interner.get(*name);
2049                    if let Some(c) = dict.consts.get(name_str) {
2050                        return Some(c.uty.clone());
2051                    }
2052                    // extern static 変数の型 (PL_utf8skip など)
2053                    if let Some(ty_str) = dict.static_types.get(name_str) {
2054                        return Some(UnifiedType::from_rust_str(ty_str));
2055                    }
2056                }
2057                // enum バリアント(C 側 EnumDict 由来)。bindings.rs では nominal
2058                // 型の variant として現れるため、属する enum 名を Named 型として
2059                // 返す。比較・ビット演算等での enum→int キャスト挿入で利用。
2060                if let Some(enum_name) = self.enum_dict.get_enum_for_variant(*name) {
2061                    let enum_str = self.interner.get(enum_name).to_string();
2062                    return Some(UnifiedType::Named(enum_str));
2063                }
2064                None
2065            }
2066            ExprKind::Cast { type_name, .. } => {
2067                Some(UnifiedType::from_rust_str(&self.type_name_to_type_str_readonly(type_name)))
2068            }
2069            ExprKind::Member { expr: base, member } | ExprKind::PtrMember { expr: base, member } => {
2070                // まず base 式の型から struct を特定し、fields_dict で
2071                // メンバ型を正確に引く (同名フィールドが別 struct に存在する
2072                // 場合の誤解決を避ける)。見つからなければ field_type_map に
2073                // フォールバック。
2074                let resolve_struct_name = |this: &Self| -> Option<String> {
2075                    // マクロ推論の type_env を優先
2076                    if let Some(info_ref) = info {
2077                        if let Some(constraints) = info_ref.type_env.expr_constraints.get(&base.id) {
2078                            if let Some(base_ty) = constraints.first().map(|c| &c.ty) {
2079                                let sn = if matches!(&expr.kind, ExprKind::PtrMember { .. }) {
2080                                    base_ty.pointee_name()
2081                                } else {
2082                                    base_ty.type_name()
2083                                };
2084                                if let Some(n) = sn {
2085                                    return Some(this.interner.get(n).to_string());
2086                                }
2087                            }
2088                        }
2089                    }
2090                    // inline 関数のローカル / パラメータ: UnifiedType 経由で
2091                    // 推論して Named を取り出す
2092                    let base_ut = this.infer_expr_type_unified(base, info)?;
2093                    let target = if matches!(&expr.kind, ExprKind::PtrMember { .. }) {
2094                        base_ut.inner_type()?
2095                    } else {
2096                        &base_ut
2097                    };
2098                    if let UnifiedType::Named(n) = target {
2099                        return Some(n.clone());
2100                    }
2101                    None
2102                };
2103
2104                let member_str = self.interner.get(*member);
2105                // fields_dict の C ソース由来型を第一優先 (同名フィールドが
2106                // 別 struct に存在するケースの誤解決を避けるため struct 名で
2107                // 限定)。ただし C 側で `[T; SVt_LAST]` のようにサイズが定数式で
2108                // 未解決の場合は `*mut T` になり配列情報を失うので、
2109                // field_type_map (bindings.rs 由来の Array) の方を優先する
2110                // フォールバックを組み合わせる。
2111                let fd_ty: Option<UnifiedType> = self.fields_dict.and_then(|fd| {
2112                    let struct_name_str = resolve_struct_name(self)?;
2113                    let struct_name = self.interner.lookup(&struct_name_str)?;
2114                    let member_ty = fd.member_type(struct_name, *member)?;
2115                    let rust_ty = member_ty.to_rust_string(self.interner);
2116                    if rust_ty.contains("/* fn */") {
2117                        return None;
2118                    }
2119                    Some(UnifiedType::from_rust_str(&rust_ty))
2120                });
2121                let ftm_ty = self.field_type_map.get(member_str).cloned();
2122                // field_type_map が配列で fields_dict がポインタなら ftm を採用。
2123                // (SVt_LAST のような unresolved サイズで fields_dict が配列情報を失うケース)
2124                match (&fd_ty, &ftm_ty) {
2125                    (Some(fd_ut), Some(ftm_ut))
2126                        if fd_ut.is_pointer() && ftm_ut.to_rust_string().starts_with('[') =>
2127                    {
2128                        return ftm_ty;
2129                    }
2130                    _ => {}
2131                }
2132                fd_ty.or(ftm_ty)
2133            }
2134            ExprKind::Deref(inner) => {
2135                let inner_ut = self.infer_expr_type_unified(inner, info)?;
2136                inner_ut.inner_type().cloned()
2137            }
2138            ExprKind::Index { expr: base, .. } => {
2139                // C の `a[i]` は `*(a + i)` と等価。base が配列 / ポインタ
2140                // 型なら要素型を返す。
2141                let base_ut = self.infer_expr_type_unified(base, info)?;
2142                base_ut.inner_type().cloned()
2143            }
2144            ExprKind::Binary { op, lhs, rhs } => {
2145                match op {
2146                    BinOp::Shl | BinOp::Shr => self.infer_expr_type_unified(lhs, info),
2147                    BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => {
2148                        let lt = self.infer_expr_type_unified(lhs, info);
2149                        let rt = self.infer_expr_type_unified(rhs, info);
2150                        match (&lt, &rt) {
2151                            (Some(l), Some(r)) => {
2152                                let ls = l.to_rust_string();
2153                                let rs = r.to_rust_string();
2154                                wider_integer_type(&ls, &rs)
2155                                    .map(|w| UnifiedType::from_rust_str(w))
2156                                    .or(lt)
2157                            }
2158                            (Some(_), None) => lt,
2159                            (None, Some(_)) => rt,
2160                            _ => None,
2161                        }
2162                    }
2163                    BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Gt
2164                    | BinOp::Le | BinOp::Ge | BinOp::LogAnd | BinOp::LogOr => {
2165                        Some(UnifiedType::Bool)
2166                    }
2167                    _ => {
2168                        // C のポインタ減算(同型ポインタ同士)は ptrdiff_t/isize を返す。
2169                        // `offset_from` メソッド呼び出しに変換されるので isize 扱い。
2170                        if *op == BinOp::Sub {
2171                            let lp = self.is_pointer_expr_unified(lhs, info)
2172                                || self.infer_expr_type_unified(lhs, info).is_some_and(|ut| ut.is_pointer());
2173                            let rp = self.is_pointer_expr_unified(rhs, info)
2174                                || self.infer_expr_type_unified(rhs, info).is_some_and(|ut| ut.is_pointer());
2175                            if lp && rp {
2176                                return Some(UnifiedType::Named("isize".to_string()));
2177                            }
2178                        }
2179                        let lt = self.infer_expr_type_unified(lhs, info);
2180                        if lt.is_some() { return lt; }
2181                        self.infer_expr_type_unified(rhs, info)
2182                    }
2183                }
2184            }
2185            ExprKind::BitNot(inner) | ExprKind::UnaryMinus(inner) => self.infer_expr_type_unified(inner, info),
2186            ExprKind::CharLit(_) => Some(UnifiedType::from_rust_str("i8")),
2187            ExprKind::UIntLit(_) => Some(UnifiedType::Int { signed: false, size: crate::unified_type::IntSize::LongLong }),
2188            // Rust の std::mem::size_of / size_of_val は `usize` を返す。
2189            // 旧実装は Int{false, Long} を返していたが、これは to_rust_string
2190            // で "c_ulong" になり usize と混同できず `u64 * usize` 等の
2191            // E0277 を起こした。明示的に Named("usize") にして区別する。
2192            ExprKind::Sizeof(_) | ExprKind::SizeofType(_) => Some(UnifiedType::Named("usize".to_string())),
2193            ExprKind::Call { func, .. } => {
2194                // メソッド呼び出し: offset/wrapping_add 等はレシーバと同じ型
2195                if let ExprKind::Member { expr: receiver, member, .. } = &func.kind {
2196                    let method_name = self.interner.get(*member);
2197                    if matches!(method_name, "offset" | "wrapping_add" | "wrapping_sub" | "wrapping_offset") {
2198                        return self.infer_expr_type_unified(receiver, info);
2199                    }
2200                }
2201                if let ExprKind::Ident(name) = &func.kind {
2202                    let func_name = self.interner.get(*name);
2203                    if let Some(ret_ut) = self.get_callee_return_type(func_name) {
2204                        return Some(ret_ut.clone());
2205                    }
2206                    // 自家生成マクロの戻り値型
2207                    if let Some(macro_info) = self.macro_ctx.macros.get(name) {
2208                        if let Some(ty) = macro_info.get_return_type() {
2209                            return Some(UnifiedType::from_rust_str(&ty.to_rust_string(self.interner)));
2210                        }
2211                    }
2212                    // inline 関数の戻り値型 (自家生成 Perl_utf8_hop 等)
2213                    if let Some(dict) = self.inline_fn_dict {
2214                        if let Some(func_def) = dict.get(*name) {
2215                            // 戻り値型を文字列組立 (読取専用 API を使用)
2216                            let base = self.base_type_str_readonly(&func_def.specs.type_specs);
2217                            let mut result = base;
2218                            let pointer_count = func_def.declarator.derived.iter()
2219                                .take_while(|d| !matches!(d, crate::ast::DerivedDecl::Function(_)))
2220                                .filter(|d| matches!(d, crate::ast::DerivedDecl::Pointer(_)))
2221                                .count();
2222                            let is_const_ptr = pointer_count == 1
2223                                && func_def.specs.qualifiers.is_const;
2224                            for _ in 0..pointer_count {
2225                                let prefix = if is_const_ptr { "*const " } else { "*mut " };
2226                                result = format!("{}{}", prefix, result);
2227                            }
2228                            return Some(UnifiedType::from_rust_str(&result));
2229                        }
2230                    }
2231                }
2232                None
2233            }
2234            ExprKind::MacroCall { name, expanded, .. } => {
2235                if let Some(macro_info) = self.macro_ctx.macros.get(name) {
2236                    if let Some(ty) = macro_info.get_return_type() {
2237                        return Some(UnifiedType::from_rust_str(&ty.to_rust_string(self.interner)));
2238                    }
2239                }
2240                self.infer_expr_type_unified(expanded, info)
2241            }
2242            ExprKind::Conditional { then_expr, else_expr, .. } => {
2243                if is_null_literal(then_expr) {
2244                    return self.infer_expr_type_unified(else_expr, info);
2245                }
2246                if is_null_literal(else_expr) {
2247                    return self.infer_expr_type_unified(then_expr, info);
2248                }
2249                let tt = self.infer_expr_type_unified(then_expr, info);
2250                let et = self.infer_expr_type_unified(else_expr, info);
2251                match (&tt, &et) {
2252                    (Some(t), Some(e)) if t.is_void_pointer() && e.is_concrete_pointer() => et,
2253                    (Some(t), Some(e)) if e.is_void_pointer() && t.is_concrete_pointer() => tt,
2254                    (Some(_), _) => tt,
2255                    (None, _) => et,
2256                }
2257            }
2258            _ => None,
2259        }
2260    }
2261
2262    /// 式がポインタ型かどうかを推定(macro/inline 統一版)
2263    fn is_pointer_expr_unified(&self, expr: &Expr, info: Option<&MacroInferInfo>) -> bool {
2264        match &expr.kind {
2265            ExprKind::Ident(name) => {
2266                if let Some(ut) = self.current_param_types.get(name) {
2267                    return ut.is_pointer();
2268                }
2269                if let Some(info) = info {
2270                    if let Some(constraints) = info.type_env.param_constraints.get(name) {
2271                        for c in constraints {
2272                            if is_type_repr_pointer(&c.ty) {
2273                                return true;
2274                            }
2275                        }
2276                    }
2277                    if let Some(expr_ids) = info.type_env.param_to_exprs.get(name) {
2278                        for expr_id in expr_ids {
2279                            if let Some(constraints) = info.type_env.expr_constraints.get(expr_id) {
2280                                for c in constraints {
2281                                    if is_type_repr_pointer(&c.ty) {
2282                                        return true;
2283                                    }
2284                                }
2285                            }
2286                        }
2287                    }
2288                }
2289                false
2290            }
2291            ExprKind::Cast { type_name, .. } => {
2292                type_name.declarator.as_ref()
2293                    .map(|d| d.derived.iter().any(|dd| matches!(dd, crate::ast::DerivedDecl::Pointer { .. })))
2294                    .unwrap_or(false)
2295            }
2296            ExprKind::AddrOf(_) => true,
2297            ExprKind::Member { member, .. } | ExprKind::PtrMember { member, .. } => {
2298                let member_str = self.interner.get(*member);
2299                self.field_type_map.get(member_str).is_some_and(|ut| ut.is_pointer())
2300            }
2301            ExprKind::Deref(inner) => {
2302                if let Some(ut) = self.infer_expr_type_unified(inner, info) {
2303                    if let Some(derefed) = ut.inner_type() {
2304                        return derefed.is_pointer();
2305                    }
2306                }
2307                false
2308            }
2309            ExprKind::Call { func, .. } | ExprKind::MacroCall { expanded: func, .. } => {
2310                let check_func = match &expr.kind {
2311                    ExprKind::MacroCall { name, .. } => {
2312                        if let Some(callee) = self.macro_ctx.macros.get(name) {
2313                            for c in &callee.type_env.return_constraints {
2314                                if is_type_repr_pointer(&c.ty) { return true; }
2315                            }
2316                        }
2317                        func
2318                    }
2319                    _ => func,
2320                };
2321                if let ExprKind::Ident(name) = &check_func.kind {
2322                    if let Some(callee) = self.macro_ctx.macros.get(name) {
2323                        for c in &callee.type_env.return_constraints {
2324                            if is_type_repr_pointer(&c.ty) { return true; }
2325                        }
2326                    }
2327                    if let Some(ret_ut) = self.get_callee_return_type(self.interner.get(*name)) {
2328                        return ret_ut.is_pointer();
2329                    }
2330                }
2331                false
2332            }
2333            ExprKind::Binary { op, lhs, rhs } => {
2334                match op {
2335                    BinOp::Add => self.is_pointer_expr_unified(lhs, info) || self.is_pointer_expr_unified(rhs, info),
2336                    BinOp::Sub => self.is_pointer_expr_unified(lhs, info) && !self.is_pointer_expr_unified(rhs, info),
2337                    _ => false,
2338                }
2339            }
2340            _ => false,
2341        }
2342    }
2343
2344    /// 式の型が `Option<fn(...)>` / `Option<unsafe extern "C" fn(...)>`
2345    /// または同型の typedef エイリアスかを判定する。
2346    ///
2347    /// bindgen 由来の関数ポインタフィールドは `Option<fn(...)>` で包まれる。
2348    /// この形式は整数 0 との `==`/`!=` 比較で `expected Option<...>` エラーを
2349    /// 起こすため、呼出側で `.is_some()`/`.is_none()` に変換する。
2350    fn is_option_fn_pointer_expr(&self, expr: &Expr, info: Option<&MacroInferInfo>) -> bool {
2351        // Member/PtrMember の直接フォールバック: infer が None を返す
2352        // (inline 関数のローカル変数など)場合に備えて、field_type_map で
2353        // フィールド名から直接 fn pointer 型か確認する。
2354        if let ExprKind::Member { member, .. } | ExprKind::PtrMember { member, .. } = &expr.kind {
2355            let member_str = self.interner.get(*member);
2356            if let Some(ut) = self.field_type_map.get(member_str) {
2357                let ty_str = ut.to_rust_string();
2358                if type_str_is_fn_pointer(&ty_str) {
2359                    return true;
2360                }
2361                if let Some(dict) = self.rust_decl_dict {
2362                    if let Some(alias) = dict.types.get(&ty_str) {
2363                        if type_str_is_fn_pointer(&alias.ty) {
2364                            return true;
2365                        }
2366                    }
2367                }
2368            }
2369        }
2370        let Some(ut) = self.infer_expr_type_unified(expr, info) else { return false };
2371        let ty_str = ut.to_rust_string();
2372        if type_str_is_fn_pointer(&ty_str) {
2373            return true;
2374        }
2375        // typedef エイリアス経由: dict.types で展開して fn 形式か確認
2376        if let Some(dict) = self.rust_decl_dict {
2377            if let Some(alias) = dict.types.get(&ty_str) {
2378                if type_str_is_fn_pointer(&alias.ty) {
2379                    return true;
2380                }
2381            }
2382        }
2383        false
2384    }
2385
2386    /// ポインタ式をbool条件に変換するラッパー(macro/inline 統一版)
2387    fn wrap_as_bool_condition(&self, expr: &Expr, expr_str: &str, info: Option<&MacroInferInfo>) -> String {
2388        if self.is_bool_expr_with_dict(expr) {
2389            return expr_str.to_string();
2390        }
2391        // パラメータが bool 型なら != 0 不要
2392        if let ExprKind::Ident(name) = &expr.kind {
2393            if let Some(ut) = self.current_param_types.get(name) {
2394                if ut.is_bool() {
2395                    return expr_str.to_string();
2396                }
2397            }
2398        }
2399        // フィールドが bool 型なら != 0 不要
2400        if let ExprKind::Member { member, .. } | ExprKind::PtrMember { member, .. } = &expr.kind {
2401            let member_str = self.interner.get(*member);
2402            if let Some(ut) = self.field_type_map.get(member_str) {
2403                if ut.is_bool() {
2404                    return expr_str.to_string();
2405                }
2406            }
2407        }
2408        // __builtin_expect(cond, val) → cond の型をチェック
2409        if let ExprKind::Call { func, args, .. } = &expr.kind {
2410            if let ExprKind::Ident(name) = &func.kind {
2411                if self.interner.get(*name) == "__builtin_expect" && !args.is_empty() {
2412                    return self.wrap_as_bool_condition(&args[0], expr_str, info);
2413                }
2414            }
2415        }
2416        if expr_str.ends_with(" as bool)") || expr_str.ends_with("!= 0)") || expr_str.ends_with(".is_null()") {
2417            return expr_str.to_string();
2418        }
2419        // Option<fn(...)> は `!= 0` で比較できず、真偽判定は .is_some()。
2420        // field_type_map 経由でフィールド名から検出する。
2421        if self.is_option_fn_pointer_expr(expr, info) {
2422            return format!("{}.is_some()", expr_str);
2423        }
2424        if self.is_pointer_expr_unified(expr, info)
2425            || self.infer_expr_type_unified(expr, info).is_some_and(|ut| ut.is_pointer()) {
2426            // `!{expr}.is_null()` 直付けだと expr が Cast の場合に
2427            // `x as T.is_null()` となり E0001 系 (cast cannot be followed
2428            // by method call)。必ず paren で包んで method chain の対象を
2429            // 明確化する。
2430            return format!("!({}).is_null()", expr_str);
2431        }
2432        format!("({} != 0)", strip_outer_parens(expr_str))
2433    }
2434
2435    /// 呼び出し先が THX マクロで、my_perl が不足しているかチェック
2436    ///
2437    /// 以下の条件を満たす場合に true を返す:
2438    /// 1. 呼び出し先が MacroInferContext.macros に存在する
2439    /// 2. その MacroInferInfo.is_thx_dependent が true
2440    /// 3. 実引数が仮引数より1つ少ない(my_perl が不足)
2441    fn needs_my_perl_for_call(&self, func_name: crate::InternedStr, actual_arg_count: usize) -> bool {
2442        // 非 threaded perl では my_perl 引数自体が存在しないので必ず false。
2443        // is_thx_dependent は既に Phase 2 で false になっているはずだが、
2444        // 防御的にここでも mode をチェック。
2445        if !self.perl_threaded {
2446            return false;
2447        }
2448        if let Some(callee_info) = self.macro_ctx.macros.get(&func_name) {
2449            if callee_info.is_thx_dependent {
2450                // THX マクロの期待引数数 = params.len() + 1 (my_perl)
2451                let expected_count = callee_info.params.len() + 1;
2452                // 実引数が1つ少ない場合、my_perl が必要
2453                return actual_arg_count + 1 == expected_count;
2454            }
2455        }
2456        false
2457    }
2458
2459    /// 式が既知の static 配列名かどうかをチェック
2460    fn is_static_array_expr(&self, expr: &Expr) -> bool {
2461        if let ExprKind::Ident(name) = &expr.kind {
2462            let name_str = self.interner.get(*name);
2463            self.bindings_info.static_arrays.contains(name_str)
2464        } else {
2465            false
2466        }
2467    }
2468
2469    /// 式が「ポインタに減衰させて `.as_ptr()` を付けるべき配列値」か判定。
2470    /// Ident (static 配列)、struct フィールドの配列型、どちらも対象。
2471    ///
2472    /// ただし flexible-array フィールド(`char data[]` 等)は
2473    /// `maybe_decay_flex_array` が `&raw const field as *mut T` に既に
2474    /// 変換済みであるため、ここでは配列扱いしない。そうしないと
2475    /// `ptr.as_ptr()` の二重適用が発生する。
2476    fn is_array_like_expr(&self, expr: &Expr, info: Option<&MacroInferInfo>) -> bool {
2477        if self.is_static_array_expr(expr) {
2478            return true;
2479        }
2480        // flex array のメンバアクセスは除外(既に pointer にデケイ済)
2481        if let ExprKind::Member { expr: base, member }
2482              | ExprKind::PtrMember { expr: base, member } = &expr.kind
2483        {
2484            if let (Some(fd), Some(info)) = (self.fields_dict, info) {
2485                if let Some(constraints) = info.type_env.expr_constraints.get(&base.id) {
2486                    if let Some(base_type) = constraints.first().map(|c| &c.ty) {
2487                        let struct_name = match &expr.kind {
2488                            ExprKind::PtrMember { .. } => base_type.pointee_name(),
2489                            _ => base_type.type_name(),
2490                        };
2491                        if let Some(sn) = struct_name {
2492                            if fd.is_flexible_array_field(sn, *member) {
2493                                return false;
2494                            }
2495                        }
2496                    }
2497                }
2498            }
2499        }
2500        if let Some(ut) = self.infer_expr_type_unified(expr, info) {
2501            let s = ut.to_rust_string();
2502            if s.starts_with('[') && s.contains(';') {
2503                return true;
2504            }
2505        }
2506        false
2507    }
2508
2509    /// フィールド名がビットフィールドメソッドかどうかをチェック
2510    ///
2511    /// 構造体名が不明な場合は、全構造体のビットフィールドメソッド名を検索
2512    fn is_bitfield_method(&self, member_name: &str) -> bool {
2513        self.bindings_info.bitfield_methods.values()
2514            .any(|methods| methods.contains(member_name))
2515    }
2516
2517    /// 呼び出し先マクロのジェネリック型パラメータ情報を取得
2518    fn get_callee_generic_params(&self, func_name: InternedStr) -> Option<&HashMap<i32, String>> {
2519        let callee_info = self.macro_ctx.macros.get(&func_name)?;
2520        if callee_info.generic_type_params.is_empty() {
2521            return None;
2522        }
2523        if callee_info.generic_type_params.keys().any(|&k| k >= 0) {
2524            Some(&callee_info.generic_type_params)
2525        } else {
2526            None
2527        }
2528    }
2529
2530    /// キャスト先の型が enum 型かどうか判定
2531    fn is_enum_cast_target(&self, type_name: &crate::ast::TypeName) -> bool {
2532        for spec in &type_name.specs.type_specs {
2533            match spec {
2534                TypeSpec::TypedefName(name) => return self.enum_dict.is_target_enum(*name),
2535                TypeSpec::Enum(_) => return true,
2536                _ => {}
2537            }
2538        }
2539        false
2540    }
2541
2542    /// 呼び出し先マクロの特定の引数位置がリテラル文字列パラメータかチェック
2543    fn callee_expects_literal_string(&self, func_name: InternedStr, arg_index: usize) -> bool {
2544        if let Some(callee_info) = self.macro_ctx.macros.get(&func_name) {
2545            return callee_info.literal_string_params.contains(&arg_index);
2546        }
2547        false
2548    }
2549
2550    /// 呼び出し先関数の指定引数位置の型を取得
2551    fn get_callee_param_type(&self, func_name: &str, arg_index: usize) -> Option<&UnifiedType> {
2552        self.rust_decl_dict?.fns.get(func_name).and_then(|f| {
2553            f.params.get(arg_index).map(|p| &p.uty)
2554        })
2555    }
2556
2557    /// 呼び出し先関数のパラメータ型を取得(inline 関数/マクロ関数もフォールバック)
2558    fn get_callee_param_type_extended(&mut self, func_name: &str, arg_index: usize) -> Option<UnifiedType> {
2559        // 0. 既知 libc 関数のハードコード型 (bindings.rs に無く、
2560        //    呼出側が `*mut c_char` を渡すが実際は `*mut c_void` が期待される
2561        //    ケースで as-cast を自動挿入するため)。
2562        if let Some(ut) = libc_fn_param_type(func_name, arg_index) {
2563            return Some(ut);
2564        }
2565        // 1. bindings.rs
2566        if let Some(ut) = self.get_callee_param_type(func_name, arg_index) {
2567            return Some(ut.clone());
2568        }
2569        if let Some(interned) = self.interner.lookup(func_name) {
2570            // 2. inline 関数
2571            if let Some(dict) = self.inline_fn_dict {
2572                if let Some(func_def) = dict.get(interned) {
2573                    for d in &func_def.declarator.derived {
2574                        if let DerivedDecl::Function(param_list) = d {
2575                            if let Some(param) = param_list.params.get(arg_index) {
2576                                let ty = self.param_type_only(param);
2577                                return Some(UnifiedType::from_rust_str(&ty));
2578                            }
2579                            break;
2580                        }
2581                    }
2582                }
2583            }
2584            // 3. 自家生成マクロ関数の type_env からパラメータ型を取得
2585            if let Some(macro_info) = self.macro_ctx.macros.get(&interned) {
2586                // THX 依存の場合、arg_index 0 は my_perl なのでスキップ。
2587                // 非 threaded では my_perl が存在しないので素通り。
2588                let macro_param_idx = if self.perl_threaded && macro_info.is_thx_dependent {
2589                    if arg_index == 0 {
2590                        return Some(UnifiedType::from_rust_str("*mut PerlInterpreter"));
2591                    }
2592                    arg_index - 1
2593                } else {
2594                    arg_index
2595                };
2596                if let Some(param) = macro_info.params.get(macro_param_idx) {
2597                    // best-tier 制約 (param.expr_id() + param_to_exprs 全 ExprId 走査)
2598                    // 宣言型 (`get_param_type`) と同じ選択方式に揃え、
2599                    // 呼出側のキャスト判定が真の宣言と一致するようにする。
2600                    if let Some(mut ty) = best_constraint_for_macro_param(macro_info, param) {
2601                        // const/mut も callee 側の最終宣言と一致させる
2602                        // (get_param_type と同じロジック: const_pointer_positions に含まれていれば const)
2603                        let should_be_const = macro_info
2604                            .const_pointer_positions
2605                            .contains(&macro_param_idx);
2606                        if should_be_const {
2607                            ty.make_outer_pointer_const();
2608                        } else if ty.has_outer_pointer() {
2609                            ty.make_outer_pointer_mut();
2610                        }
2611                        let rust_ty = ty.to_rust_string(self.interner);
2612                        return Some(UnifiedType::from_rust_str(&rust_ty));
2613                    }
2614                }
2615            }
2616        }
2617        None
2618    }
2619
2620    /// 呼び出し先関数の指定引数位置が bool 型かどうか判定(自家生成マクロも参照)
2621    fn callee_param_is_bool(&self, func_name: &str, arg_index: usize) -> bool {
2622        // 1. bindings.rs の関数
2623        if let Some(param_ut) = self.get_callee_param_type(func_name, arg_index) {
2624            return param_ut.is_bool();
2625        }
2626        // 2. 自家生成マクロ関数のパラメータ型
2627        if let Some(interned) = self.interner.lookup(func_name) {
2628            if let Some(macro_info) = self.macro_ctx.macros.get(&interned) {
2629                // THX マクロは my_perl が自動挿入されるのでオフセットを引く。
2630                // 非 threaded では my_perl 注入が無いのでオフセット 0。
2631                let macro_arg_index = if self.perl_threaded
2632                    && macro_info.is_thx_dependent
2633                    && arg_index > 0
2634                {
2635                    arg_index - 1
2636                } else {
2637                    arg_index
2638                };
2639                if let Some(param) = macro_info.params.get(macro_arg_index) {
2640                    // type_env からパラメータの型制約を取得
2641                    if let Some(expr_ids) = macro_info.type_env.param_to_exprs.get(&param.name) {
2642                        for expr_id in expr_ids {
2643                            if let Some(constraints) = macro_info.type_env.expr_constraints.get(expr_id) {
2644                                for c in constraints {
2645                                    let rust_ty = c.ty.to_rust_string(self.interner);
2646                                    if rust_ty == "bool" {
2647                                        return true;
2648                                    }
2649                                }
2650                            }
2651                        }
2652                    }
2653                }
2654            }
2655            // 3. 自家生成 inline 関数のパラメータ型
2656            if let Some(dict) = self.inline_fn_dict {
2657                if let Some(func_def) = dict.get(interned) {
2658                    for d in &func_def.declarator.derived {
2659                        if let DerivedDecl::Function(param_list) = d {
2660                            if let Some(param) = param_list.params.get(arg_index) {
2661                                let has_bool = param.specs.type_specs.iter().any(|ts| matches!(ts, TypeSpec::Bool));
2662                                let has_pointer = param.declarator.as_ref().map_or(false, |decl| {
2663                                    decl.derived.iter().any(|d| matches!(d, DerivedDecl::Pointer(_)))
2664                                });
2665                                if has_bool && !has_pointer {
2666                                    return true;
2667                                }
2668                            }
2669                            break;
2670                        }
2671                    }
2672                }
2673            }
2674        }
2675        false
2676    }
2677
2678    /// 呼び出し先関数の戻り値型を取得
2679    fn get_callee_return_type(&self, func_name: &str) -> Option<&UnifiedType> {
2680        self.rust_decl_dict?.fns.get(func_name).and_then(|f| {
2681            f.uret_ty.as_ref()
2682        })
2683    }
2684
2685    /// `UnifiedType` が bindings.rs 上の Rust enum 型を指すかを判定。
2686    /// (C 側では int 互換だが、Rust 側は nominal 型なので、整数演算には
2687    /// `as <int>` キャストが必要になる)
2688    fn is_rust_enum_type(&self, ut: &UnifiedType) -> bool {
2689        if let UnifiedType::Named(name) = ut {
2690            if let Some(dict) = self.rust_decl_dict {
2691                return dict.enums.contains(name.as_str());
2692            }
2693        }
2694        false
2695    }
2696
2697    /// 式が bool を返すかどうかを判定(関数の戻り値型も考慮)
2698    fn is_bool_expr_with_dict(&self, expr: &Expr) -> bool {
2699        if is_boolean_expr_recursive(expr, self.interner) {
2700            return true;
2701        }
2702        // 配列インデックス: 配列要素型が bool なら bool
2703        if let ExprKind::Index { expr: base, .. } = &expr.kind {
2704            if let ExprKind::Ident(name) = &base.kind {
2705                if let Some(dict) = self.rust_decl_dict {
2706                    let name_str = self.interner.get(*name);
2707                    if let Some(c) = dict.consts.get(name_str) {
2708                        if let Some(inner) = c.uty.inner_type() {
2709                            if inner.is_bool() {
2710                                return true;
2711                            }
2712                        }
2713                    }
2714                    // static 配列: 名前が PL_valid_types_* なら bool 配列
2715                    if dict.statics.contains(name_str) && name_str.starts_with("PL_valid_types_") {
2716                        return true;
2717                    }
2718                }
2719            }
2720        }
2721        // パラメータが bool 型
2722        if let ExprKind::Ident(name) = &expr.kind {
2723            if let Some(ut) = self.current_param_types.get(name) {
2724                if ut.is_bool() {
2725                    return true;
2726                }
2727            }
2728        }
2729        // フィールドが bool 型
2730        if let ExprKind::Member { member, .. } | ExprKind::PtrMember { member, .. } = &expr.kind {
2731            let member_str = self.interner.get(*member);
2732            if let Some(ut) = self.field_type_map.get(member_str) {
2733                if ut.is_bool() {
2734                    return true;
2735                }
2736            }
2737        }
2738        // 関数呼び出しの戻り値型が bool かチェック
2739        if let ExprKind::Call { func, .. } = &expr.kind {
2740            if let ExprKind::Ident(name) = &func.kind {
2741                // 0. codegen で bool と判定されたマクロ
2742                if self.bool_return_macros.contains(name) {
2743                    return true;
2744                }
2745                let func_name = self.interner.get(*name);
2746                // 1. bindings.rs の関数
2747                if let Some(ret_ut) = self.get_callee_return_type(func_name) {
2748                    return ret_ut.is_bool();
2749                }
2750                // 2. 自家生成マクロ関数の戻り値型
2751                if let Some(macro_info) = self.macro_ctx.macros.get(name) {
2752                    if let Some(ty) = macro_info.get_return_type() {
2753                        let rust_ty = ty.to_rust_string(self.interner);
2754                        return rust_ty == "bool";
2755                    }
2756                }
2757                // 3. 自家生成 inline 関数の戻り値型
2758                if let Some(dict) = self.inline_fn_dict {
2759                    if let Some(func_def) = dict.get(*name) {
2760                        let has_bool_return = func_def.specs.type_specs.iter().any(|ts| matches!(ts, TypeSpec::Bool));
2761                        let has_return_pointer = func_def.declarator.derived.iter().any(|d| matches!(d, DerivedDecl::Pointer(_)));
2762                        if has_bool_return && !has_return_pointer {
2763                            return true;
2764                        }
2765                    }
2766                }
2767            }
2768        }
2769        // MacroCall の場合も bool_return_macros をチェック
2770        if let ExprKind::MacroCall { name, .. } = &expr.kind {
2771            if self.bool_return_macros.contains(name) {
2772                return true;
2773            }
2774        }
2775        false
2776    }
2777
2778    /// 式の最内部にある literal_string_param の Ident を探す
2779    /// identity builtin(ASSERT_IS_LITERAL 等)を透過して中身をチェック
2780    fn find_literal_string_ident<'b>(&self, expr: &'b Expr) -> Option<&'b InternedStr> {
2781        match &expr.kind {
2782            ExprKind::Ident(name) if self.current_literal_string_params.contains(name) => {
2783                Some(name)
2784            }
2785            ExprKind::Call { func, args } if args.len() == 1 => {
2786                // identity builtin (ASSERT_IS_LITERAL, ASSERT_IS_PTR, ASSERT_NOT_PTR)
2787                if let ExprKind::Ident(fname) = &func.kind {
2788                    let func_name = self.interner.get(*fname);
2789                    if func_name == "ASSERT_IS_LITERAL"
2790                        || func_name == "ASSERT_IS_PTR"
2791                        || func_name == "ASSERT_NOT_PTR"
2792                    {
2793                        return self.find_literal_string_ident(&args[0]);
2794                    }
2795                }
2796                None
2797            }
2798            _ => None,
2799        }
2800    }
2801
2802
2803    /// マクロ呼び出し形式で出力すべきかを判定
2804    ///
2805    /// 以下の場合にマクロ呼び出し形式で出力する:
2806    /// - MacroInferContext に登録されており、生成対象である
2807    ///
2808    /// そうでない場合は展開形式で出力する。
2809    fn should_emit_as_macro_call(&self, name: crate::InternedStr) -> bool {
2810        // MacroInferContext にマクロ情報があり、パース可能なら生成対象
2811        if let Some(info) = self.macro_ctx.macros.get(&name) {
2812            // パース成功し、利用不可関数を呼ばないマクロのみ
2813            return info.is_parseable() && !info.calls_unavailable;
2814        }
2815        false
2816    }
2817
2818    /// 不完全マーカー: 型が不明
2819    fn unknown_marker(&mut self) -> &'static str {
2820        self.incomplete_count += 1;
2821        "/* unknown */"
2822    }
2823
2824    /// 不完全マーカー: TODO
2825    fn todo_marker(&mut self, msg: &str) -> String {
2826        self.incomplete_count += 1;
2827        format!("/* TODO: {} */", msg)
2828    }
2829
2830    /// 不完全マーカー: 型
2831    fn type_marker(&mut self) -> &'static str {
2832        self.incomplete_count += 1;
2833        "/* type */"
2834    }
2835
2836    /// Declaration から変数名を収集して current_local_names に追加
2837    /// ローカル変数の型も current_param_types に登録(ポインタ検出用)
2838    fn collect_decl_names(&mut self, decl: &Declaration) {
2839        let base_type = self.decl_specs_to_rust(&decl.specs);
2840        for init_decl in &decl.declarators {
2841            if let Some(name) = init_decl.declarator.name {
2842                self.current_local_names.insert(name);
2843                let ty = self.apply_derived_to_type(&base_type, &init_decl.declarator.derived);
2844                self.current_param_types.insert(name, UnifiedType::from_rust_str(&ty));
2845            }
2846        }
2847    }
2848
2849    /// 関数本体全体を再帰的に走査して、ネストした compound 内・StmtExpr 内・
2850    /// for ループ初期化部の Declaration を全て `current_local_names` に追加する。
2851    /// scope 厳密性は犠牲にして「同一名はどのスコープでも解決済み」と扱う簡易版。
2852    /// `STMT_START { let v = ...; ... } STMT_END` 展開で生まれる block-local
2853    /// 変数を未解決と誤検出しないようにする。
2854    fn collect_local_names_recursive(&mut self, body: &CompoundStmt) {
2855        for item in &body.items {
2856            self.collect_local_names_from_block_item(item);
2857        }
2858    }
2859
2860    fn collect_local_names_from_block_item(&mut self, item: &BlockItem) {
2861        match item {
2862            BlockItem::Decl(d) => self.collect_decl_names(d),
2863            BlockItem::Stmt(s) => self.collect_local_names_from_stmt(s),
2864        }
2865    }
2866
2867    fn collect_local_names_from_stmt(&mut self, stmt: &Stmt) {
2868        match stmt {
2869            Stmt::Compound(c) => self.collect_local_names_recursive(c),
2870            Stmt::If { then_stmt, else_stmt, cond, .. } => {
2871                self.collect_local_names_from_expr(cond);
2872                self.collect_local_names_from_stmt(then_stmt);
2873                if let Some(es) = else_stmt {
2874                    self.collect_local_names_from_stmt(es);
2875                }
2876            }
2877            Stmt::Switch { body, expr, .. } => {
2878                self.collect_local_names_from_expr(expr);
2879                self.collect_local_names_from_stmt(body);
2880            }
2881            Stmt::While { body, cond, .. } => {
2882                self.collect_local_names_from_expr(cond);
2883                self.collect_local_names_from_stmt(body);
2884            }
2885            Stmt::DoWhile { body, cond, .. } => {
2886                self.collect_local_names_from_stmt(body);
2887                self.collect_local_names_from_expr(cond);
2888            }
2889            Stmt::For { init, cond, step, body, .. } => {
2890                if let Some(i) = init {
2891                    match i {
2892                        ForInit::Decl(d) => self.collect_decl_names(d),
2893                        ForInit::Expr(e) => self.collect_local_names_from_expr(e),
2894                    }
2895                }
2896                if let Some(c) = cond { self.collect_local_names_from_expr(c); }
2897                if let Some(s) = step { self.collect_local_names_from_expr(s); }
2898                self.collect_local_names_from_stmt(body);
2899            }
2900            Stmt::Expr(Some(e), _) => self.collect_local_names_from_expr(e),
2901            Stmt::Return(Some(e), _) => self.collect_local_names_from_expr(e),
2902            Stmt::Label { stmt, .. } | Stmt::Case { stmt, .. } | Stmt::Default { stmt, .. } => {
2903                self.collect_local_names_from_stmt(stmt);
2904            }
2905            _ => {}
2906        }
2907    }
2908
2909    fn collect_local_names_from_expr(&mut self, expr: &Expr) {
2910        if let ExprKind::StmtExpr(c) = &expr.kind {
2911            self.collect_local_names_recursive(c);
2912        }
2913        // 他の式ノードに含まれる StmtExpr は普通存在しない(C 文法上)が、
2914        // 念のため簡易的に再帰しておく
2915        match &expr.kind {
2916            ExprKind::Binary { lhs, rhs, .. }
2917            | ExprKind::Assign { lhs, rhs, .. }
2918            | ExprKind::Comma { lhs, rhs } => {
2919                self.collect_local_names_from_expr(lhs);
2920                self.collect_local_names_from_expr(rhs);
2921            }
2922            ExprKind::Conditional { cond, then_expr, else_expr } => {
2923                self.collect_local_names_from_expr(cond);
2924                self.collect_local_names_from_expr(then_expr);
2925                self.collect_local_names_from_expr(else_expr);
2926            }
2927            ExprKind::Cast { expr: e, .. }
2928            | ExprKind::AddrOf(e) | ExprKind::Deref(e)
2929            | ExprKind::UnaryPlus(e) | ExprKind::UnaryMinus(e)
2930            | ExprKind::BitNot(e) | ExprKind::LogNot(e)
2931            | ExprKind::PreInc(e) | ExprKind::PreDec(e)
2932            | ExprKind::PostInc(e) | ExprKind::PostDec(e)
2933            | ExprKind::Sizeof(e)
2934            | ExprKind::Member { expr: e, .. } | ExprKind::PtrMember { expr: e, .. } => {
2935                self.collect_local_names_from_expr(e);
2936            }
2937            ExprKind::Call { func, args } => {
2938                self.collect_local_names_from_expr(func);
2939                for a in args { self.collect_local_names_from_expr(a); }
2940            }
2941            ExprKind::Index { expr: e, index } => {
2942                self.collect_local_names_from_expr(e);
2943                self.collect_local_names_from_expr(index);
2944            }
2945            _ => {}
2946        }
2947    }
2948
2949    /// Declaration からローカル変数の型のみ収集して current_param_types に追加
2950    /// (current_local_names には追加しない — 未解決シンボル検出に影響しないように)
2951    fn collect_decl_types(&mut self, decl: &Declaration) {
2952        let base_type = self.decl_specs_to_rust(&decl.specs);
2953        for init_decl in &decl.declarators {
2954            if let Some(name) = init_decl.declarator.name {
2955                let ty = self.apply_derived_to_type(&base_type, &init_decl.declarator.derived);
2956                self.current_param_types.insert(name, UnifiedType::from_rust_str(&ty));
2957            }
2958        }
2959    }
2960
2961    /// バッファに行を書き込み
2962    fn writeln(&mut self, s: &str) {
2963        self.buffer.push_str(s);
2964        self.buffer.push('\n');
2965    }
2966
2967    /// 生成結果を取得(self を消費)
2968    fn into_generated_code(self) -> GeneratedCode {
2969        GeneratedCode {
2970            code: self.buffer,
2971            incomplete_count: self.incomplete_count,
2972            unresolved_names: self.unresolved_names,
2973            used_libc_fns: self.used_libc_fns,
2974            codegen_errors: self.codegen_errors,
2975        }
2976    }
2977
2978    /// マクロ関数を生成(self を消費)
2979    pub fn generate_macro(mut self, info: &MacroInferInfo) -> GeneratedCode {
2980        let name_str = self.interner.get(info.name);
2981
2982        // ローカルスコープ: マクロのパラメータ名を登録
2983        for p in &info.params {
2984            self.current_local_names.insert(p.name);
2985        }
2986
2987        // 型パラメータマップを構築
2988        self.current_type_param_map = info.generic_type_params.iter()
2989            .filter(|(idx, _)| **idx >= 0)
2990            .filter_map(|(idx, generic_name)| {
2991                info.params.get(*idx as usize).map(|p| (p.name, generic_name.clone()))
2992            })
2993            .collect();
2994
2995        // 型パラメータになったパラメータは通常パラメータとしては存在しないので
2996        // current_local_names から除外する(ジェネリック誤検出時に unresolved 検出するため)
2997        for (name, _) in &self.current_type_param_map {
2998            self.current_local_names.remove(name);
2999        }
3000
3001        // リテラル文字列パラメータの名前集合を構築
3002        self.current_literal_string_params = info.literal_string_params.iter()
3003            .filter_map(|&idx| info.params.get(idx).map(|p| p.name))
3004            .collect();
3005
3006        // ジェネリック句を生成
3007        let generic_clause = self.build_generic_clause(info);
3008
3009        // パラメータリストを構築(型情報付き)
3010        // type/cast パラメータは値引数ではないので除外
3011        let params_with_types = self.build_param_list(info);
3012
3013        // 戻り値の型を取得(current_return_type にもセット)
3014        let return_type = self.get_return_type(info);
3015        self.current_return_type = Some(UnifiedType::from_rust_str(&return_type));
3016
3017        // 型推論ダンプ
3018        if self.dump_types_for.as_deref() == Some(name_str) {
3019            self.dump_type_info(name_str, info, &params_with_types, &return_type);
3020        }
3021
3022        // THX 依存の場合は my_perl パラメータを追加。
3023        // 非 threaded perl では my_perl 自体が存在しないので注入しない。
3024        let thx_param = if self.perl_threaded && info.is_thx_dependent {
3025            "my_perl: *mut PerlInterpreter"
3026        } else {
3027            ""
3028        };
3029
3030        // 関数シグネチャ
3031        let params_str = if thx_param.is_empty() {
3032            params_with_types.clone()
3033        } else if params_with_types.is_empty() {
3034            thx_param.to_string()
3035        } else {
3036            format!("{}, {}", thx_param, params_with_types)
3037        };
3038
3039        // AST ダンプ(デバッグ用)
3040        self.dump_ast_comment_for_expr(name_str, &info.parse_result);
3041
3042        // ドキュメントコメント
3043        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
3044        let generic_info = if !generic_clause.is_empty() { " [generic]" } else { "" };
3045        self.writeln(&format!("/// {}{}{} - macro function", name_str, thx_info, generic_info));
3046        self.writeln("#[inline]");
3047        self.writeln("#[allow(unsafe_op_in_unsafe_fn)]");
3048
3049        // 関数定義(ジェネリック句付き)
3050        self.writeln(&format!("pub unsafe fn {}{}({}) -> {} {{", name_str, generic_clause, params_str, return_type));
3051
3052        // unsafe 操作(関数呼び出し or デリファレンス)を含む場合のみ unsafe ブロックを生成
3053        let needs_unsafe = info.has_unsafe_ops();
3054        let body_indent = if needs_unsafe { "        " } else { "    " };
3055
3056        if needs_unsafe {
3057            self.writeln("    unsafe {");
3058        }
3059
3060        match &info.parse_result {
3061            ParseResult::Expression(expr) => {
3062                let type_hint = self.current_return_type.as_ref().map(|ut| ut.to_rust_string());
3063                let mut syn_expr = self.build_syn_expr_with_type_hint(expr, Some(info), type_hint.as_deref());
3064
3065                if self.current_return_type.as_ref().is_some_and(|ut| ut.is_void()) {
3066                    let s = normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr));
3067                    self.writeln(&format!("{}{};", body_indent, s));
3068                } else if self.current_return_type.as_ref().is_some_and(|ut| ut.is_bool())
3069                    && !self.is_bool_expr_with_dict(expr)
3070                    && !crate::syn_codegen::is_bool_syn_expr(&syn_expr) {
3071                    if self.is_pointer_expr_unified(expr, Some(info))
3072                        || self.infer_expr_type_unified(expr, Some(info)).is_some_and(|ut| ut.is_pointer()) {
3073                        let s = normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr));
3074                        // `!x.is_null()` 直付けだと x が cast の場合に
3075                        // `x as T.is_null()` と解釈される。必ず括弧で包む。
3076                        self.writeln(&format!("{}!({}).is_null()", body_indent, s));
3077                    } else {
3078                        syn_expr = crate::syn_codegen::wrap_as_bool(syn_expr);
3079                        let s = normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr));
3080                        self.writeln(&format!("{}{}", body_indent, s));
3081                    }
3082                } else {
3083                    syn_expr = self.cast_return_syn_expr_if_needed(expr, Some(info), syn_expr);
3084                    let s = normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr));
3085                    self.writeln(&format!("{}{}", body_indent, s));
3086                }
3087            }
3088            ParseResult::Statement(block_items) => {
3089                for item in block_items {
3090                    if let BlockItem::Stmt(stmt) = item {
3091                        let rust_stmt = self.stmt_to_rust(stmt, info);
3092                        self.writeln(&format!("{}{}", body_indent, rust_stmt));
3093                    }
3094                }
3095            }
3096            ParseResult::Unparseable(_) => {
3097                self.writeln(&format!("{}unimplemented!()", body_indent));
3098            }
3099        }
3100
3101        if needs_unsafe {
3102            self.writeln("    }");
3103        }
3104
3105        self.writeln("}");
3106        self.writeln("");
3107
3108        self.into_generated_code()
3109    }
3110
3111    /// ジェネリック句を生成(例: "<T>" or "<T, U>")
3112    fn build_generic_clause(&self, info: &MacroInferInfo) -> String {
3113        if info.generic_type_params.is_empty() {
3114            return String::new();
3115        }
3116
3117        // 型パラメータを収集(重複排除、ソート)
3118        let mut params: Vec<&String> = info.generic_type_params.values().collect();
3119        params.sort();
3120        params.dedup();
3121
3122        format!("<{}>", params.iter().map(|s| s.as_str()).collect::<Vec<_>>().join(", "))
3123    }
3124
3125    /// パラメータリストを構築(型情報付き)
3126    /// type/cast パラメータは型パラメータなので値引数からは除外する
3127    /// 副作用: 各パラメータの型を current_param_types に登録する
3128    fn build_param_list(&mut self, info: &MacroInferInfo) -> String {
3129        let mut_params = collect_mut_params(&info.parse_result, &info.params);
3130        let mut parts = Vec::new();
3131        for (i, p) in info.params.iter().enumerate() {
3132            if info.generic_type_params.contains_key(&(i as i32)) {
3133                continue;
3134            }
3135            let name = escape_rust_keyword(self.interner.get(p.name));
3136            let ty = self.get_param_type(p, info, i);
3137            // current_param_types に登録(bool 判定等で使用)
3138            self.current_param_types.insert(p.name, UnifiedType::from_rust_str(&ty));
3139            let mut_prefix = if mut_params.contains(&p.name) { "mut " } else { "" };
3140            parts.push(format!("{}{}: {}", mut_prefix, name, ty));
3141        }
3142        parts.join(", ")
3143    }
3144
3145    /// パラメータの型を取得
3146    fn get_param_type(&mut self, param: &MacroParam, info: &MacroInferInfo, param_index: usize) -> String {
3147        // ジェネリック型パラメータかチェック
3148        if let Some(generic_name) = info.generic_type_params.get(&(param_index as i32)) {
3149            return generic_name.clone();
3150        }
3151
3152        // リテラル文字列パラメータかチェック(apidoc の "..." 引数)
3153        if info.literal_string_params.contains(&param_index) {
3154            return "&str".to_string();
3155        }
3156
3157        let should_be_const = self.const_pointer_positions.contains(&param_index);
3158
3159        if let Some(mut ty) = best_constraint_for_macro_param(info, param) {
3160            if should_be_const {
3161                ty.make_outer_pointer_const();
3162            } else if ty.has_outer_pointer() {
3163                // must-mut: Phase 2 で *mut と確定 → *const になっていたら *mut に戻す
3164                ty.make_outer_pointer_mut();
3165            }
3166            return self.type_repr_to_rust(&ty);
3167        }
3168
3169        self.unknown_marker().to_string()
3170    }
3171
3172    /// 戻り値の型を取得
3173    ///
3174    /// ジェネリック戻り値型を優先し、なければ
3175    /// MacroInferInfo::get_return_type() を使用して、
3176    /// return_constraints(apidoc由来)を expr_constraints より優先する
3177    fn get_return_type(&mut self, info: &MacroInferInfo) -> String {
3178        // ジェネリック戻り値型かチェック(-1 = return type)
3179        if let Some(generic_name) = info.generic_type_params.get(&-1) {
3180            return generic_name.clone();
3181        }
3182
3183        // 依存順パスで bool と判定されていればそのまま bool を返す
3184        if self.is_bool_return {
3185            return "bool".to_string();
3186        }
3187
3188        match &info.parse_result {
3189            ParseResult::Expression(expr) => {
3190                if let Some(ty) = info.get_return_type() {
3191                    let mut ty_str = self.type_repr_to_rust(ty);
3192                    if ty_str != "()" {
3193                        // 式の推論型がポインタで const なら戻り値も const に
3194                        if ty_str.contains("*mut") {
3195                            if let Some(expr_ut) = self.infer_expr_type(expr, info) {
3196                                if expr_ut.is_const_pointer() {
3197                                    ty_str = ty_str.replace("*mut", "*const");
3198                                }
3199                            }
3200                        }
3201                        return ty_str;
3202                    }
3203                    // "()" が返された場合: 式の実際の型を確認
3204                    // 式が本当に void を返す(void 関数呼び出し等)なら "()" で正しい
3205                    // そうでなければ型推論の誤りなのでフォールバック
3206                    if let Some(ut) = self.infer_expr_type(expr, info) {
3207                        let s = ut.to_rust_string();
3208                        if s != "()" {
3209                            return s;
3210                        }
3211                    }
3212                    // 式型推論でも "()" → void で正しい
3213                    return ty_str;
3214                }
3215                self.unknown_marker().to_string()
3216            }
3217            ParseResult::Statement(_) => "()".to_string(),
3218            ParseResult::Unparseable(_) => "()".to_string(),
3219        }
3220    }
3221
3222    /// TypeRepr を Rust 型文字列に変換
3223    ///
3224    /// 戻り値に `/*` が含まれていたら不完全型としてカウントする
3225    fn type_repr_to_rust(&mut self, ty: &crate::type_repr::TypeRepr) -> String {
3226        let result = ty.to_rust_string(self.interner);
3227        let result = self.substitute_type_params(&result);
3228        if result.contains("/*") {
3229            self.incomplete_count += 1;
3230        }
3231        result
3232    }
3233
3234    /// 型文字列中の型パラメータ名を generic 名に置換
3235    fn substitute_type_params(&self, type_str: &str) -> String {
3236        if self.current_type_param_map.is_empty() {
3237            return type_str.to_string();
3238        }
3239        let mut result = type_str.to_string();
3240        for (param_name, generic_name) in &self.current_type_param_map {
3241            let name_str = self.interner.get(*param_name);
3242            // 単語境界を考慮した置換(部分文字列一致を避ける)
3243            result = replace_word(&result, name_str, generic_name);
3244        }
3245        result
3246    }
3247
3248    /// MUTABLE_PTR パターンを検出
3249    ///
3250    /// `({ void *p_ = (expr); p_; })` のような構造を検出し、
3251    /// 初期化子の式を返す。
3252    fn detect_mutable_ptr_pattern<'b>(&self, compound: &'b CompoundStmt) -> Option<&'b Expr> {
3253        // 2つの要素: 宣言 + 式文
3254        if compound.items.len() != 2 {
3255            return None;
3256        }
3257
3258        // 最初の要素: 宣言
3259        let decl = match &compound.items[0] {
3260            BlockItem::Decl(d) => d,
3261            _ => return None,
3262        };
3263
3264        // 宣言子が1つで、初期化子がある
3265        if decl.declarators.len() != 1 {
3266            return None;
3267        }
3268        let init_decl = &decl.declarators[0];
3269        let declared_name = init_decl.declarator.name?;
3270        let init = init_decl.init.as_ref()?;
3271
3272        // 初期化子は式
3273        let init_expr = match init {
3274            Initializer::Expr(e) => e.as_ref(),
3275            _ => return None,
3276        };
3277
3278        // 2番目の要素: 式文で、宣言した変数を参照
3279        let last_expr = match &compound.items[1] {
3280            BlockItem::Stmt(Stmt::Expr(Some(e), _)) => e,
3281            _ => return None,
3282        };
3283
3284        // 最後の式が宣言した変数への参照
3285        if let ExprKind::Ident(name) = &last_expr.kind {
3286            if *name == declared_name {
3287                return Some(init_expr);
3288            }
3289        }
3290
3291        None
3292    }
3293
3294    // ================================================================
3295    // syn::Expr ベースの式構築 (Step 1+)
3296    // ================================================================
3297
3298    /// flexible array member の field access を `&raw const place as *mut T`
3299    /// に変換する。配列名→ポインタ decay の C 慣用句を Rust で正しく表現する。
3300    ///
3301    /// 検出条件: base 式の TypeRepr から typedef/struct 名を取り、
3302    /// `FieldsDict::flexible_array_element` が要素型を返した場合のみ変換。
3303    /// それ以外は `access` をそのまま返す。
3304    fn maybe_decay_flex_array(
3305        &self,
3306        access: syn::Expr,
3307        base: &Expr,
3308        member: InternedStr,
3309        info: Option<&MacroInferInfo>,
3310        is_ptr_member: bool,
3311    ) -> syn::Expr {
3312        let Some(fd) = self.fields_dict else { return access; };
3313        let Some(info) = info else { return access; };
3314        let Some(constraints) = info.type_env.expr_constraints.get(&base.id) else {
3315            return access;
3316        };
3317        let Some(base_type) = constraints.first().map(|c| &c.ty) else {
3318            return access;
3319        };
3320        let struct_name = if is_ptr_member {
3321            base_type.pointee_name()
3322        } else {
3323            base_type.type_name()
3324        };
3325        let Some(struct_name) = struct_name else { return access; };
3326        let Some(elem) = fd.flexible_array_element(struct_name, member) else {
3327            return access;
3328        };
3329        // `&raw const access as *mut <element>` を生成
3330        let elem_str = elem.to_rust_string(self.interner);
3331        let target_ty_str = format!("*mut {}", elem_str);
3332        let raw_const = syn::Expr::RawAddr(syn::ExprRawAddr {
3333            attrs: vec![],
3334            and_token: Default::default(),
3335            raw: Default::default(),
3336            mutability: syn::PointerMutability::Const(Default::default()),
3337            expr: Box::new(access),
3338        });
3339        crate::syn_codegen::insert_cast(raw_const, crate::syn_codegen::parse_type(&target_ty_str))
3340    }
3341
3342    /// `&MACRO(args)` の AddrOf inner が「自家生成マクロへの Call」で、
3343    /// 呼び出し先が **Expression body**(lvalue chain として展開可能)なら、
3344    /// 本体式を引数で alpha 置換した `Expr` を返す。
3345    ///
3346    /// 用途: `&GvSV(gv)` のような C 慣用句で、Rust 側の wrap 関数が
3347    /// temporary を返すため `&raw mut <fn_call>` が E0745 になる問題の回避。
3348    /// マクロ本体を inline 展開して `&raw mut (*GvGP(gv)).gp_sv` のような
3349    /// 真の place 式に変換する。
3350    fn try_inline_call_for_addrof(&self, inner: &Expr) -> Option<Expr> {
3351        let (callee_id, args) = match &inner.kind {
3352            ExprKind::Call { func, args } => match &func.kind {
3353                ExprKind::Ident(name) => (*name, args),
3354                _ => return None,
3355            },
3356            _ => return None,
3357        };
3358
3359        let callee_info = self.macro_ctx.macros.get(&callee_id)?;
3360        let body = match &callee_info.parse_result {
3361            ParseResult::Expression(e) => e,
3362            _ => return None,
3363        };
3364
3365        // THX 依存だと第一引数が my_perl で arg と zip がずれる → 当面非対応
3366        if callee_info.is_thx_dependent {
3367            return None;
3368        }
3369        if callee_info.params.len() != args.len() {
3370            return None;
3371        }
3372
3373        // param_name → arg_expr の置換マップを構築
3374        let mut subs: HashMap<InternedStr, &Expr> = HashMap::new();
3375        for (param, arg) in callee_info.params.iter().zip(args.iter()) {
3376            subs.insert(param.name, arg);
3377        }
3378
3379        let mut inlined = (**body).clone();
3380        substitute_idents(&mut inlined, &subs);
3381        Some(inlined)
3382    }
3383
3384    /// C AST の式を syn::Expr に変換する(macro/inline 統一)
3385    ///
3386    /// `info` が Some の場合はマクロ用、None の場合は inline 用。
3387    /// 未対応の ExprKind は expr_to_rust_ctx のフォールバック文字列を syn::parse_str で変換する。
3388    fn build_syn_expr(&mut self, expr: &Expr, info: Option<&MacroInferInfo>) -> syn::Expr {
3389        use crate::syn_codegen::*;
3390
3391        match &expr.kind {
3392            ExprKind::Ident(name) => {
3393                // lvalue展開時のパラメータ置換
3394                if let Some(subst) = self.param_substitutions.get(name) {
3395                    // 置換文字列をパース
3396                    return syn::parse_str(subst).unwrap_or_else(|_| int_lit(0));
3397                }
3398                let name_str = self.interner.get(*name);
3399                // libc 関数の使用を記録
3400                if LIBC_FUNCTIONS.contains(&name_str) {
3401                    self.used_libc_fns.insert(name_str.to_string());
3402                }
3403                // 未解決シンボルチェック
3404                if !self.current_local_names.contains(name)
3405                    && !self.enum_dict.is_enum_variant(*name)
3406                    && !self.known_symbols.contains(name_str)
3407                {
3408                    let s = name_str.to_string();
3409                    if !self.unresolved_names.contains(&s) {
3410                        self.unresolved_names.push(s);
3411                    }
3412                }
3413                // true/false は Rust の bool リテラルとして出力(r#true 回避)
3414                if name_str == "true" || name_str == "false" {
3415                    return syn::Expr::Lit(syn::ExprLit {
3416                        attrs: vec![],
3417                        lit: syn::Lit::Bool(syn::LitBool {
3418                            value: name_str == "true",
3419                            span: proc_macro2::Span::call_site(),
3420                        }),
3421                    });
3422                }
3423                let escaped = escape_rust_keyword(name_str);
3424                // extern static 配列はポインタとして使われるため raw pointer に減衰させる。
3425                //
3426                // Rust 2024 edition では `static mut` への暗黙の shared reference が
3427                // hard error 化された (`creating a shared reference to mutable static`)。
3428                // `.as_ptr()` は内部で `&self -> *const T` の参照経由を行うため、
3429                // `static mut PL_fold_locale: [u8; N]` のような mutable static に対して
3430                // 直接呼ぶと当該 lint を踏む。
3431                //
3432                // - `(&raw const NAME[0])` は const 評価で `[N=0]` の OOB を踏む
3433                //   (bindgen が不明サイズの extern static を `[T; 0]` で出すため)。
3434                // - `(&raw const NAME) as *const u8` は型情報を捨てるため `.offset(i)`
3435                //   が byte 単位になり、要素配列で計算が壊れる。
3436                // - 正解は **`(&raw const NAME) as *const T`**。bindings から要素型 T
3437                //   を取り出して埋め込む。取り出せなかったら u8 にフォールバック。
3438                if self.bindings_info.static_arrays.contains(name_str) {
3439                    let elem = self.bindings_info.static_array_element_type(name_str)
3440                        .unwrap_or_else(|| "u8".to_string());
3441                    return syn::parse_str(&format!(
3442                        "((&raw const {}) as *const {})",
3443                        escaped, elem
3444                    ))
3445                    .unwrap_or_else(|_| int_lit(0));
3446                }
3447                syn::Expr::Path(syn::ExprPath {
3448                    attrs: vec![],
3449                    qself: None,
3450                    path: ident(&escaped).into(),
3451                })
3452            }
3453            ExprKind::IntLit(n) => int_lit(*n),
3454            ExprKind::UIntLit(n) => {
3455                let lit = syn::LitInt::new(&format!("{}u64", n), proc_macro2::Span::call_site());
3456                syn::Expr::Lit(syn::ExprLit { attrs: vec![], lit: syn::Lit::Int(lit) })
3457            }
3458            ExprKind::FloatLit(f) => {
3459                let lit = syn::LitFloat::new(&format!("{}", f), proc_macro2::Span::call_site());
3460                syn::Expr::Lit(syn::ExprLit { attrs: vec![], lit: syn::Lit::Float(lit) })
3461            }
3462            ExprKind::CharLit(c) => {
3463                let s = if c.is_ascii() {
3464                    format!("b'{}' as i8", escape_char(*c))
3465                } else {
3466                    format!("0x{:02x}u8 as i8", c)
3467                };
3468                syn::parse_str(&s).unwrap_or_else(|_| int_lit(0))
3469            }
3470            ExprKind::StringLit(s) => {
3471                syn::parse_str(&format!("c\"{}\"", escape_string(s)))
3472                    .unwrap_or_else(|_| int_lit(0))
3473            }
3474            ExprKind::Deref(inner) => {
3475                let e = self.build_syn_expr(inner, info);
3476                deref(e)
3477            }
3478            ExprKind::AddrOf(inner) => {
3479                // C の `&MACRO(args)` パターン: マクロが lvalue を返すことを
3480                // 期待する C コード。Rust では MACRO が unsafe fn として
3481                // wrap されるため戻り値が temporary になり `&raw mut <call>`
3482                // が E0745 を起こす。callee の本体式を inline 展開して
3483                // lvalue 性を回復する。
3484                if let Some(inlined) = self.try_inline_call_for_addrof(inner) {
3485                    let e = self.build_syn_expr(&inlined, info);
3486                    return addr_of_mut(e);
3487                }
3488                let e = self.build_syn_expr(inner, info);
3489                addr_of_mut(e)
3490            }
3491            ExprKind::UnaryPlus(inner) => {
3492                self.build_syn_expr(inner, info)
3493            }
3494            ExprKind::BitNot(inner) => {
3495                let e = self.build_syn_expr(inner, info);
3496                syn::Expr::Unary(syn::ExprUnary {
3497                    attrs: vec![],
3498                    op: syn::UnOp::Not(Default::default()),
3499                    expr: Box::new(e),
3500                })
3501            }
3502            ExprKind::Member { expr: base, member } => {
3503                let e = self.build_syn_expr(base, info);
3504                let m = self.interner.get(*member);
3505                if self.is_bitfield_method(m) {
3506                    // bitfield → メソッド呼び出し
3507                    syn::Expr::MethodCall(syn::ExprMethodCall {
3508                        attrs: vec![],
3509                        receiver: Box::new(e),
3510                        dot_token: Default::default(),
3511                        method: ident(m),
3512                        turbofish: None,
3513                        paren_token: Default::default(),
3514                        args: syn::punctuated::Punctuated::new(),
3515                    })
3516                } else {
3517                    let access = field_access(e, m);
3518                    self.maybe_decay_flex_array(access, base, *member, info, /*is_ptr_member=*/false)
3519                }
3520            }
3521            ExprKind::PtrMember { expr: base, member } => {
3522                let e = self.build_syn_expr(base, info);
3523                let m = self.interner.get(*member);
3524                let derefed = deref(e);
3525                if self.is_bitfield_method(m) {
3526                    syn::Expr::MethodCall(syn::ExprMethodCall {
3527                        attrs: vec![],
3528                        receiver: Box::new(derefed),
3529                        dot_token: Default::default(),
3530                        method: ident(m),
3531                        turbofish: None,
3532                        paren_token: Default::default(),
3533                        args: syn::punctuated::Punctuated::new(),
3534                    })
3535                } else {
3536                    let access = field_access(derefed, m);
3537                    self.maybe_decay_flex_array(access, base, *member, info, /*is_ptr_member=*/true)
3538                }
3539            }
3540            ExprKind::Comma { lhs, rhs } => {
3541                let l = self.build_syn_expr(lhs, info);
3542                let r = self.build_syn_expr(rhs, info);
3543                // C カンマ `(A, B)` の翻訳。LHS の値は捨てるが、A が
3544                // assignment-as-expression の場合 codegen は `{ stmt; trailing }`
3545                // のような trailing 値付きブロックを作る(例: `*fp |= X` →
3546                // `{ *fp |= X; *fp }`)。これを文の位置で `;` 付きに置くと
3547                // Rust の trailing 単項式・論理演算・must_use 戻り値が discarded で
3548                // CI の `-D warnings` を踏む。
3549                //
3550                // 条件付き `let _ = A;` wrap: A が値を返すと判明している
3551                // パターン(trailing-expr 付き block / 論理演算 / 単項 / 関数呼出)
3552                // のみ wrap する。`{ assert!(...); }` のように常に `()` を返す
3553                // 形式まで wrap すると、既存の生成コードを不必要に汚すため除外。
3554                if expr_yields_value_for_stmt_use(&l) {
3555                    let l_str = expr_to_string(&l);
3556                    let r_str = expr_to_string(&r);
3557                    syn::parse_str(&format!("{{ let _ = {}; {} }}", l_str, r_str))
3558                        .unwrap_or_else(|_| int_lit(0))
3559                } else {
3560                    syn::Expr::Block(syn::ExprBlock {
3561                        attrs: vec![],
3562                        label: None,
3563                        block: syn::Block {
3564                            brace_token: Default::default(),
3565                            stmts: vec![
3566                                syn::Stmt::Expr(l, Some(Default::default())),
3567                                syn::Stmt::Expr(r, None),
3568                            ],
3569                        },
3570                    })
3571                }
3572            }
3573            ExprKind::UnaryMinus(inner) => {
3574                let e = self.build_syn_expr(inner, info);
3575                // unsigned 型のキャスト結果に対する負号は wrapping_neg を使用
3576                let e_str = expr_to_string(&e);
3577                if is_unsigned_cast_expr(&e_str) {
3578                    return syn::parse_str(&format!("({}).wrapping_neg()", e_str.trim_start_matches('-')))
3579                        .unwrap_or_else(|_| int_lit(0));
3580                }
3581                if let Some(ut) = self.infer_expr_type_unified(inner, info) {
3582                    let ts = ut.to_rust_string();
3583                    if matches!(normalize_integer_type(&ts), Some("usize" | "u8" | "u16" | "u32" | "u64")) {
3584                        self.codegen_errors.push(format!("cannot negate unsigned type: -({}: {})", e_str, ts));
3585                    }
3586                }
3587                syn::Expr::Unary(syn::ExprUnary {
3588                    attrs: vec![],
3589                    op: syn::UnOp::Neg(Default::default()),
3590                    expr: Box::new(e),
3591                })
3592            }
3593            ExprKind::LogNot(inner) => {
3594                // C の `!"literal"` は 0 (false)。文字列リテラルは常に非 NULL。
3595                if matches!(&inner.kind, ExprKind::StringLit(_)) {
3596                    return syn::parse_str("false").unwrap_or_else(|_| int_lit(0));
3597                }
3598                let e = self.build_syn_expr(inner, info);
3599                if !self.is_bool_expr_with_dict(inner)
3600                    && (self.is_pointer_expr_unified(inner, info)
3601                        || self.infer_expr_type_unified(inner, info).is_some_and(|ut| ut.is_pointer()))
3602                {
3603                    // C の `!ptr` は「ptr が NULL か」そのもの。`.is_null()` が
3604                    // 否定を内包するので、外側に ! を重ねてはならない
3605                    // (かつて二重否定になっており、SvPVXtrue 等の null ガードが
3606                    // 反転していた)。
3607                    return syn::Expr::MethodCall(syn::ExprMethodCall {
3608                        attrs: vec![],
3609                        receiver: Box::new(e),
3610                        dot_token: Default::default(),
3611                        method: ident("is_null"),
3612                        turbofish: None,
3613                        paren_token: Default::default(),
3614                        args: syn::punctuated::Punctuated::new(),
3615                    });
3616                }
3617                let bool_e = if self.is_bool_expr_with_dict(inner) {
3618                    e
3619                } else {
3620                    // 整数 → != 0 して bool に変換、否定は外側 ! が担当
3621                    wrap_as_bool(e)
3622                };
3623                syn::Expr::Unary(syn::ExprUnary {
3624                    attrs: vec![],
3625                    op: syn::UnOp::Not(Default::default()),
3626                    expr: Box::new(bool_e),
3627                })
3628            }
3629            ExprKind::Cast { type_name, expr: inner } => {
3630                let t = self.type_name_to_rust(type_name);
3631                // C の慣用表現 `(unsigned)-1` は最大値を意味する。
3632                // `-1 as T` では E0600 (usize に対する単項 - は不可) になるため、
3633                // `T::MAX` に置換する。`-N` 一般は今は扱わず、`-1` のみ対応。
3634                if is_unsigned_integer_target(&t) {
3635                    if let ExprKind::UnaryMinus(minus_inner) = &inner.kind {
3636                        if matches!(&minus_inner.kind,
3637                            ExprKind::IntLit(1) | ExprKind::UIntLit(1))
3638                        {
3639                            return syn::parse_str(&format!("{}::MAX", t))
3640                                .unwrap_or_else(|_| int_lit(0));
3641                        }
3642                    }
3643                }
3644                // C の const-cast パターン `(T*)&place`:
3645                // place が `*const` ポインタ deref 経由(例: `(c)->field` で
3646                // `c: *const PERL_CONTEXT`)だと `&raw mut place` が E0596
3647                // になるため、`&raw const place as *mut T` で const を剥がす。
3648                // place が元から mut でも結果は等価(raw pointer の as cast は
3649                // mut/const を問わない)。
3650                if (t.starts_with("*mut ") || t.starts_with("*const "))
3651                    && matches!(&inner.kind, ExprKind::AddrOf(_))
3652                {
3653                    if let ExprKind::AddrOf(addrof_inner) = &inner.kind {
3654                        // AddrOf の inner が「callee マクロ呼び出し」なら inline 展開
3655                        let inlined_owned;
3656                        let inner_to_build: &Expr =
3657                            if let Some(inlined) = self.try_inline_call_for_addrof(addrof_inner) {
3658                                inlined_owned = inlined;
3659                                &inlined_owned
3660                            } else {
3661                                addrof_inner
3662                            };
3663                        let inner_e = self.build_syn_expr(inner_to_build, info);
3664                        let raw_const = syn::Expr::RawAddr(syn::ExprRawAddr {
3665                            attrs: vec![],
3666                            and_token: Default::default(),
3667                            raw: Default::default(),
3668                            mutability: syn::PointerMutability::Const(Default::default()),
3669                            expr: Box::new(inner_e),
3670                        });
3671                        return insert_cast(raw_const, parse_type(&t));
3672                    }
3673                }
3674                let e = self.build_syn_expr(inner, info);
3675                if t == "()" {
3676                    // void キャスト → 式の値を `let _` で捨てる。
3677                    // 単純な `{ expr; }` だと `must_use` 関数の戻り値(size_of_val 等)、
3678                    // 論理演算 (`a || b`)、単項式 (`*ptr`) を捨てたときに
3679                    // unused_must_use / unused_logical_op / unused_unary lint で
3680                    // CI の `-D warnings` が落ちる。`let _ = expr;` ならどんな式でも
3681                    // 「使った」扱いになり、副作用ある式(assignment, fn call)でも安全。
3682                    let e_str = expr_to_string(&e);
3683                    return syn::parse_str(&format!("{{ let _ = {}; }}", e_str))
3684                        .unwrap_or_else(|_| int_lit(0));
3685                }
3686                if t == "bool" {
3687                    // bool キャスト
3688                    if self.is_bool_expr_with_dict(inner) {
3689                        return e;
3690                    }
3691                    if self.is_pointer_expr_unified(inner, info)
3692                        || self.infer_expr_type_unified(inner, info).is_some_and(|ut| ut.is_pointer()) {
3693                        // ポインタ → !ptr.is_null()
3694                        let is_null = syn::Expr::MethodCall(syn::ExprMethodCall {
3695                            attrs: vec![],
3696                            receiver: Box::new(e),
3697                            dot_token: Default::default(),
3698                            method: ident("is_null"),
3699                            turbofish: None,
3700                            paren_token: Default::default(),
3701                            args: syn::punctuated::Punctuated::new(),
3702                        });
3703                        return syn::Expr::Unary(syn::ExprUnary {
3704                            attrs: vec![],
3705                            op: syn::UnOp::Not(Default::default()),
3706                            expr: Box::new(is_null),
3707                        });
3708                    }
3709                    return wrap_as_bool(e);
3710                }
3711                if self.is_enum_cast_target(type_name) {
3712                    // enum キャスト → transmute
3713                    let e_str = expr_to_string(&e);
3714                    return syn::parse_str(&format!("std::mem::transmute::<_, {}>({})", t, e_str))
3715                        .unwrap_or_else(|_| int_lit(0));
3716                }
3717                insert_cast(e, parse_type(&t))
3718            }
3719            ExprKind::Sizeof(inner) => {
3720                // sizeof(literal_string_param) → param.len() + 1
3721                if let ExprKind::Ident(name) = &inner.kind {
3722                    if self.current_literal_string_params.contains(name) {
3723                        let param = escape_rust_keyword(self.interner.get(*name));
3724                        return syn::parse_str(&format!("({}.len() + 1)", param))
3725                            .unwrap_or_else(|_| int_lit(0));
3726                    }
3727                }
3728                let e = self.build_syn_expr(inner, info);
3729                let e_str = expr_to_string(&e);
3730                // `&` 単項はフィールド/関数呼出より低優先なため、
3731                // `&len + 1` は `(&len) + 1` と解釈される。
3732                // 常に `&(expr)` と paren で包み、normalize_parens で
3733                // 不要な括弧を除去する。
3734                syn::parse_str(&format!("std::mem::size_of_val(&({}))", e_str))
3735                    .unwrap_or_else(|_| int_lit(0))
3736            }
3737            ExprKind::SizeofType(type_name) => {
3738                let t = self.type_name_to_rust(type_name);
3739                syn::parse_str(&format!("std::mem::size_of::<{}>()", t))
3740                    .unwrap_or_else(|_| int_lit(0))
3741            }
3742            ExprKind::Index { expr: base, index } => {
3743                use crate::syn_codegen::*;
3744                let i = self.build_syn_expr(index, info);
3745                let i_isize = cast_syn_expr(i, "isize");
3746                let base_expr: syn::Expr = if self.is_array_like_expr(base, info) {
3747                    // 配列ベースを raw pointer に減衰させる。
3748                    // - 通常: `array.as_ptr()`
3749                    // - extern static (mutable static 含む): `((&raw const NAME) as *const T)`
3750                    //   (Rust 2024 で `static mut` への shared reference が hard error 化。
3751                    //   `.as_ptr()` 経由の暗黙参照を避ける。要素型 T は bindings から取得)
3752                    let raw_ptr_expr: syn::Expr = if let ExprKind::Ident(n) = &base.kind {
3753                        let name_str = self.interner.get(*n);
3754                        let escaped = escape_rust_keyword(name_str);
3755                        if self.bindings_info.static_arrays.contains(name_str) {
3756                            let elem = self.bindings_info
3757                                .static_array_element_type(name_str)
3758                                .unwrap_or_else(|| "u8".to_string());
3759                            syn::parse_str(&format!(
3760                                "((&raw const {}) as *const {})",
3761                                escaped, elem
3762                            ))
3763                            .unwrap_or_else(|_| int_lit(0))
3764                        } else {
3765                            let id = ident_expr(escaped.as_str());
3766                            method_call(id, "as_ptr", vec![])
3767                        }
3768                    } else {
3769                        let b = self.build_syn_expr(base, info);
3770                        method_call(b, "as_ptr", vec![])
3771                    };
3772                    // 要素型を可能な限り抽出して `*mut ELEM` にキャスト。
3773                    // `as_ptr()` / `&raw const` どちらも `*const T` だが、後段で
3774                    // `&mut a[i]` を取るときに E0596 を避けるため mut へ寄せる。
3775                    let elem_str = self.infer_expr_type_unified(base, info)
3776                        .and_then(|ut| ut.inner_type().cloned())
3777                        .map(|inner| inner.to_rust_string());
3778                    if let Some(elem) = elem_str {
3779                        cast_syn_expr(raw_ptr_expr, &format!("*mut {}", elem))
3780                    } else {
3781                        raw_ptr_expr
3782                    }
3783                } else {
3784                    self.build_syn_expr(base, info)
3785                };
3786                let offset_call = method_call(base_expr, "offset", vec![i_isize]);
3787                deref(offset_call)
3788            }
3789            ExprKind::Conditional { cond, then_expr, else_expr } => {
3790                let c = self.build_syn_expr(cond, info);
3791                let c_str = expr_to_string(&c);
3792                let cond_str = self.wrap_as_bool_condition(cond, &c_str, info);
3793                let cond_syn: syn::Expr = syn::parse_str(&cond_str).unwrap_or(c);
3794
3795                let type_hint = self.current_return_type.as_ref().map(|ut| ut.to_rust_string());
3796                let tt = self.infer_expr_type_unified(then_expr, info);
3797                let et = self.infer_expr_type_unified(else_expr, info);
3798
3799                // Fix 3: type_hint ベースの null→null_ptr, 0/1→bool 変換
3800                if let Some(ref hint) = type_hint {
3801                    let hint_ut = UnifiedType::from_rust_str(hint);
3802                    if hint_ut.is_pointer() {
3803                        // type_hint (current_return_type) はマクロ全体の戻り値で、
3804                        // call 引数内の入れ子三項にも渡ってくる。反対 arm の実推論型が
3805                        // 非ポインタ (整数フラグ等) なら、この 0 はフラグの 0 であって
3806                        // NULL ではない (例: 5.44 hv_fetch の
3807                        // `HV_FETCH_JUST_SV | (lval ? HV_FETCH_LVALUE : 0)`)。
3808                        // その場合は null 化せず arm ベースのフォールバックに任せる
3809                        if is_null_literal(else_expr)
3810                            && tt.as_ref().map_or(true, |t| t.is_pointer())
3811                        {
3812                            let t = self.build_syn_expr(then_expr, info);
3813                            let e: syn::Expr = syn::parse_str(&null_ptr_expr(&hint_ut))
3814                                .unwrap_or_else(|_| int_lit(0));
3815                            return if_else(cond_syn, t, e);
3816                        }
3817                        if is_null_literal(then_expr)
3818                            && et.as_ref().map_or(true, |t| t.is_pointer())
3819                        {
3820                            let t: syn::Expr = syn::parse_str(&null_ptr_expr(&hint_ut))
3821                                .unwrap_or_else(|_| int_lit(0));
3822                            let e = self.build_syn_expr(else_expr, info);
3823                            return if_else(cond_syn, t, e);
3824                        }
3825                    }
3826                    // 整数型の type_hint + 片方が null リテラル → null を 0 に。
3827                    // C `cond ? i : 0` の 0 がマクロ展開で NULL になっているケース。
3828                    if normalize_integer_type(hint).is_some() {
3829                        if is_null_literal(else_expr) {
3830                            let t = self.build_syn_expr(then_expr, info);
3831                            return if_else(cond_syn, t, int_lit(0));
3832                        }
3833                        if is_null_literal(then_expr) {
3834                            let e = self.build_syn_expr(else_expr, info);
3835                            return if_else(cond_syn, int_lit(0), e);
3836                        }
3837                    }
3838                    if hint_ut.is_bool() {
3839                        let then_syn = match &then_expr.kind {
3840                            ExprKind::IntLit(0) => syn::parse_str("false").unwrap(),
3841                            ExprKind::IntLit(1) => syn::parse_str("true").unwrap(),
3842                            _ => self.build_syn_expr(then_expr, info),
3843                        };
3844                        let else_syn = match &else_expr.kind {
3845                            ExprKind::IntLit(0) => syn::parse_str("false").unwrap(),
3846                            ExprKind::IntLit(1) => syn::parse_str("true").unwrap(),
3847                            _ => self.build_syn_expr(else_expr, info),
3848                        };
3849                        return if_else(cond_syn, then_syn, else_syn);
3850                    }
3851                }
3852
3853                // null リテラル分岐の型推論(type_hint がない場合のフォールバック)
3854                let then_syn = if is_null_literal(then_expr) {
3855                    if let Some(ref eut) = et {
3856                        if eut.is_pointer() {
3857                            syn::parse_str(&null_ptr_expr(eut)).unwrap_or_else(|_| int_lit(0))
3858                        } else { self.build_syn_expr(then_expr, info) }
3859                    } else { self.build_syn_expr(then_expr, info) }
3860                } else { self.build_syn_expr(then_expr, info) };
3861
3862                let else_syn = if is_null_literal(else_expr) {
3863                    if let Some(ref tut) = tt {
3864                        if tut.is_pointer() {
3865                            syn::parse_str(&null_ptr_expr(tut)).unwrap_or_else(|_| int_lit(0))
3866                        } else { self.build_syn_expr(else_expr, info) }
3867                    } else { self.build_syn_expr(else_expr, info) }
3868                } else { self.build_syn_expr(else_expr, info) };
3869
3870                // Fix 2: wider_integer_type キャスト
3871                if let (Some(tut), Some(eut)) = (&tt, &et) {
3872                    let ts = tut.to_rust_string();
3873                    let es = eut.to_rust_string();
3874                    if let (Some(tn), Some(en)) = (normalize_integer_type(&ts), normalize_integer_type(&es)) {
3875                        if tn != en {
3876                            if let Some(wider) = wider_integer_type(&ts, &es) {
3877                                let (then_final, else_final) = if normalize_integer_type(&ts) != Some(wider) {
3878                                    (cast_syn_expr(then_syn, wider), else_syn)
3879                                } else {
3880                                    (then_syn, cast_syn_expr(else_syn, wider))
3881                                };
3882                                return if_else(cond_syn, then_final, else_final);
3883                            }
3884                        }
3885                    }
3886                    // SV サブタイプ間: 両枝を共通型 (type_hint 優先、なければ then 型)
3887                    // に揃えて if/else 型整合を確保する。
3888                    if tut.is_pointer() && eut.is_pointer() && ts != es
3889                        && is_sv_subtype_cast(tut, eut)
3890                    {
3891                        // type_hint が void (`()` や `c_void`) の場合は cast 対象に
3892                        // しない (return 型が void の文脈で分岐値は捨てられる)。
3893                        let target_str = type_hint.as_deref()
3894                            .filter(|t| *t != "()" && !UnifiedType::from_rust_str(t).is_void())
3895                            .unwrap_or(&ts)
3896                            .to_string();
3897                        return if_else(
3898                            cond_syn,
3899                            cast_syn_expr(then_syn, &target_str),
3900                            cast_syn_expr(else_syn, &target_str),
3901                        );
3902                    }
3903                }
3904
3905                if_else(cond_syn, then_syn, else_syn)
3906            }
3907            ExprKind::Binary { op, lhs, rhs } => {
3908                // sizeof(literal_string_param) - 1 → param.len()
3909                if *op == BinOp::Sub {
3910                    if let ExprKind::Sizeof(inner) = &lhs.kind {
3911                        if let ExprKind::Ident(name) = &inner.kind {
3912                            if self.current_literal_string_params.contains(name) {
3913                                if let ExprKind::IntLit(1) = &rhs.kind {
3914                                    let param = escape_rust_keyword(self.interner.get(*name));
3915                                    return syn::parse_str(&format!("{}.len()", param))
3916                                        .unwrap_or_else(|_| int_lit(0));
3917                                }
3918                            }
3919                        }
3920                    }
3921                }
3922
3923                // C 文字列リテラル vs 0 比較 → 常に非 NULL (c"..." は &CStr)
3924                //   `c"..." == 0` → false / `c"..." != 0` → true
3925                if matches!(op, BinOp::Eq | BinOp::Ne) {
3926                    let s_eq = |s: &ExprKind| matches!(s, ExprKind::StringLit(_));
3927                    let lhs_is_str = s_eq(&lhs.kind);
3928                    let rhs_is_str = s_eq(&rhs.kind);
3929                    if (lhs_is_str && is_null_literal(rhs))
3930                       || (rhs_is_str && is_null_literal(lhs))
3931                    {
3932                        return syn::parse_str(
3933                            if *op == BinOp::Eq { "false" } else { "true" }
3934                        ).unwrap_or_else(|_| int_lit(0));
3935                    }
3936                }
3937                // Option<fn(...)> == 0 / != 0 → .is_none() / .is_some()
3938                // bindgen の関数ポインタフィールドは Option で包まれるため、
3939                // ポインタ null 比較より先に Option 判定を行う。
3940                if matches!(op, BinOp::Eq | BinOp::Ne) {
3941                    let opt_lhs = (is_null_literal(rhs) || matches!(&rhs.kind, ExprKind::IntLit(0)))
3942                        && self.is_option_fn_pointer_expr(lhs, info);
3943                    let opt_rhs = (is_null_literal(lhs) || matches!(&lhs.kind, ExprKind::IntLit(0)))
3944                        && self.is_option_fn_pointer_expr(rhs, info);
3945                    if opt_lhs || opt_rhs {
3946                        let receiver_expr = if opt_lhs { lhs } else { rhs };
3947                        let r = self.build_syn_expr(receiver_expr, info);
3948                        let method = if *op == BinOp::Eq { "is_none" } else { "is_some" };
3949                        return syn::Expr::MethodCall(syn::ExprMethodCall {
3950                            attrs: vec![], receiver: Box::new(r), dot_token: Default::default(),
3951                            method: ident(method), turbofish: None,
3952                            paren_token: Default::default(), args: syn::punctuated::Punctuated::new(),
3953                        });
3954                    }
3955                }
3956                // ポインタ == 0 / != 0 → .is_null()
3957                if matches!(op, BinOp::Eq | BinOp::Ne) {
3958                    if is_null_literal(rhs) {
3959                        if self.is_pointer_expr_unified(lhs, info)
3960                            || self.infer_expr_type_unified(lhs, info).is_some_and(|ut| ut.is_pointer()) {
3961                            let l = self.build_syn_expr(lhs, info);
3962                            let is_null = syn::Expr::MethodCall(syn::ExprMethodCall {
3963                                attrs: vec![], receiver: Box::new(l), dot_token: Default::default(),
3964                                method: ident("is_null"), turbofish: None,
3965                                paren_token: Default::default(), args: syn::punctuated::Punctuated::new(),
3966                            });
3967                            return if *op == BinOp::Eq { is_null } else {
3968                                syn::Expr::Unary(syn::ExprUnary {
3969                                    attrs: vec![], op: syn::UnOp::Not(Default::default()),
3970                                    expr: Box::new(is_null),
3971                                })
3972                            };
3973                        }
3974                    }
3975                    if is_null_literal(lhs) {
3976                        if self.is_pointer_expr_unified(rhs, info)
3977                            || self.infer_expr_type_unified(rhs, info).is_some_and(|ut| ut.is_pointer()) {
3978                            let r = self.build_syn_expr(rhs, info);
3979                            let is_null = syn::Expr::MethodCall(syn::ExprMethodCall {
3980                                attrs: vec![], receiver: Box::new(r), dot_token: Default::default(),
3981                                method: ident("is_null"), turbofish: None,
3982                                paren_token: Default::default(), args: syn::punctuated::Punctuated::new(),
3983                            });
3984                            return if *op == BinOp::Eq { is_null } else {
3985                                syn::Expr::Unary(syn::ExprUnary {
3986                                    attrs: vec![], op: syn::UnOp::Not(Default::default()),
3987                                    expr: Box::new(is_null),
3988                                })
3989                            };
3990                        }
3991                    }
3992                    // bool_expr != 0 → bool_expr, bool_expr == 0 → !bool_expr
3993                    if self.is_bool_expr_with_dict(lhs) {
3994                        match (&rhs.kind, op) {
3995                            (ExprKind::IntLit(0), BinOp::Ne) | (ExprKind::IntLit(1), BinOp::Eq) => {
3996                                return self.build_syn_expr(lhs, info);
3997                            }
3998                            (ExprKind::IntLit(0), BinOp::Eq) | (ExprKind::IntLit(1), BinOp::Ne) => {
3999                                let l = self.build_syn_expr(lhs, info);
4000                                return syn::Expr::Unary(syn::ExprUnary {
4001                                    attrs: vec![], op: syn::UnOp::Not(Default::default()),
4002                                    expr: Box::new(l),
4003                                });
4004                            }
4005                            _ => {}
4006                        }
4007                    }
4008                    if self.is_bool_expr_with_dict(rhs) {
4009                        match (&lhs.kind, op) {
4010                            (ExprKind::IntLit(0), BinOp::Ne) | (ExprKind::IntLit(1), BinOp::Eq) => {
4011                                return self.build_syn_expr(rhs, info);
4012                            }
4013                            (ExprKind::IntLit(0), BinOp::Eq) | (ExprKind::IntLit(1), BinOp::Ne) => {
4014                                let r = self.build_syn_expr(rhs, info);
4015                                return syn::Expr::Unary(syn::ExprUnary {
4016                                    attrs: vec![], op: syn::UnOp::Not(Default::default()),
4017                                    expr: Box::new(r),
4018                                });
4019                            }
4020                            _ => {}
4021                        }
4022                    }
4023                }
4024
4025                // ポインタ ± 整数 → .offset()
4026                if matches!(op, BinOp::Add | BinOp::Sub) {
4027                    // static 配列の Ident (`bodies_by_type` 等) は build_syn_expr
4028                    // が既に `.as_ptr()` を付加するため、`l_arr` には含めない。
4029                    // ここで再度 `.as_ptr()` を被せると *const T に対して呼ばれて
4030                    // E0599 になる。非 Ident の「フィールド直値が配列型」に限定。
4031                    let l_arr = !self.is_static_array_expr(lhs)
4032                        && self.is_array_like_expr(lhs, info);
4033                    let r_arr = !self.is_static_array_expr(rhs)
4034                        && self.is_array_like_expr(rhs, info);
4035                    let lp = l_arr
4036                        || self.is_static_array_expr(lhs)
4037                        || self.is_pointer_expr_unified(lhs, info)
4038                        || self.infer_expr_type_unified(lhs, info).is_some_and(|ut| ut.is_pointer());
4039                    let rp = r_arr
4040                        || self.is_static_array_expr(rhs)
4041                        || self.is_pointer_expr_unified(rhs, info)
4042                        || self.infer_expr_type_unified(rhs, info).is_some_and(|ut| ut.is_pointer());
4043                    // 配列値に対して `(arr.as_ptr() as *mut ELEM)` で mut pointer を
4044                    // 作るヘルパ。l_arr は field-access の配列(build_syn_expr が
4045                    // `.as_ptr()` を付けない)、is_static_array は Ident の static
4046                    // 配列(build_syn_expr が既に `.as_ptr()` を付ける)。どちらの
4047                    // ケースでも結果が `*const T` にならないよう `*mut T` へ cast
4048                    // する。
4049                    let l_is_static_arr = self.is_static_array_expr(lhs);
4050                    let r_is_static_arr = self.is_static_array_expr(rhs);
4051                    let cast_to_mut = |this: &mut Self, expr: syn::Expr, arr_expr: &Expr,
4052                                        needs_as_ptr: bool| -> syn::Expr {
4053                        let elem = this.infer_expr_type_unified(arr_expr, info)
4054                            .and_then(|ut| ut.inner_type().cloned())
4055                            .map(|u| u.to_rust_string());
4056                        let base = if needs_as_ptr {
4057                            crate::syn_codegen::method_call(expr, "as_ptr", vec![])
4058                        } else {
4059                            expr
4060                        };
4061                        if let Some(e) = elem {
4062                            crate::syn_codegen::cast_syn_expr(base, &format!("*mut {}", e))
4063                        } else {
4064                            base
4065                        }
4066                    };
4067                    if lp && !rp {
4068                        let l = self.build_syn_expr(lhs, info);
4069                        let l = if l_arr {
4070                            cast_to_mut(self, l, lhs, /*needs_as_ptr=*/true)
4071                        } else if l_is_static_arr {
4072                            cast_to_mut(self, l, lhs, /*needs_as_ptr=*/false)
4073                        } else {
4074                            l
4075                        };
4076                        let r = self.build_syn_expr(rhs, info);
4077                        let r_isize = crate::syn_codegen::cast_syn_expr(r, "isize");
4078                        let arg = if *op == BinOp::Add { r_isize } else {
4079                            syn::Expr::Unary(syn::ExprUnary {
4080                                attrs: vec![],
4081                                op: syn::UnOp::Neg(Default::default()),
4082                                expr: Box::new(r_isize),
4083                            })
4084                        };
4085                        return crate::syn_codegen::method_call(l, "offset", vec![arg]);
4086                    }
4087                    if rp && !lp && *op == BinOp::Add {
4088                        let l = self.build_syn_expr(lhs, info);
4089                        let r = self.build_syn_expr(rhs, info);
4090                        let r = if r_arr {
4091                            cast_to_mut(self, r, rhs, /*needs_as_ptr=*/true)
4092                        } else if r_is_static_arr {
4093                            cast_to_mut(self, r, rhs, /*needs_as_ptr=*/false)
4094                        } else {
4095                            r
4096                        };
4097                        let l_isize = crate::syn_codegen::cast_syn_expr(l, "isize");
4098                        return crate::syn_codegen::method_call(r, "offset", vec![l_isize]);
4099                    }
4100                    if lp && rp && *op == BinOp::Sub {
4101                        let l = self.build_syn_expr(lhs, info);
4102                        let r = self.build_syn_expr(rhs, info);
4103                        return crate::syn_codegen::method_call(l, "offset_from", vec![r]);
4104                    }
4105                }
4106
4107                // float vs int literal → float に変換
4108                if matches!(&rhs.kind, ExprKind::IntLit(_)) {
4109                    if let Some(lut) = self.infer_expr_type_unified(lhs, info) {
4110                        if lut.is_float() {
4111                            if let ExprKind::IntLit(v) = &rhs.kind {
4112                                let l = self.build_syn_expr(lhs, info);
4113                                let l_str = expr_to_string(&l);
4114                                return syn::parse_str(&format!("{} {} {}.0", l_str, bin_op_to_rust(*op), v))
4115                                    .unwrap_or_else(|_| int_lit(0));
4116                            }
4117                        }
4118                    }
4119                }
4120                if matches!(&lhs.kind, ExprKind::IntLit(_)) {
4121                    if let Some(rut) = self.infer_expr_type_unified(rhs, info) {
4122                        if rut.is_float() {
4123                            if let ExprKind::IntLit(v) = &lhs.kind {
4124                                let r = self.build_syn_expr(rhs, info);
4125                                let r_str = expr_to_string(&r);
4126                                return syn::parse_str(&format!("{}.0 {} {}", v, bin_op_to_rust(*op), r_str))
4127                                    .unwrap_or_else(|_| int_lit(0));
4128                            }
4129                        }
4130                    }
4131                }
4132
4133                // ポインタ比較で const/mut が違う場合の cast。
4134                // `*mut T < *const T` は Rust で E0308(types differ in mutability)。
4135                // rhs を lhs の型に合わせる(wrapper の呼出規約で lhs が mut、
4136                // callee 由来の rhs が const になりやすい)。
4137                if matches!(op, BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Eq | BinOp::Ne) {
4138                    if let (Some(lut), Some(rut)) =
4139                        (self.infer_expr_type_unified(lhs, info),
4140                         self.infer_expr_type_unified(rhs, info))
4141                    {
4142                        if lut.is_pointer() && rut.is_pointer()
4143                            && pointer_inner_compatible(&lut, &rut)
4144                            && (lut.is_const_pointer() != rut.is_const_pointer()
4145                                || lut.to_rust_string() != rut.to_rust_string())
4146                        {
4147                            let l = self.build_syn_expr(lhs, info);
4148                            let r = self.build_syn_expr(rhs, info);
4149                            let target = lut.to_rust_string();
4150                            return syn::Expr::Binary(syn::ExprBinary {
4151                                attrs: vec![], left: Box::new(l),
4152                                op: crate::syn_codegen::to_syn_binop(*op),
4153                                right: Box::new(crate::syn_codegen::cast_syn_expr(r, &target)),
4154                            });
4155                        }
4156                    }
4157                }
4158
4159                let l = self.build_syn_expr(lhs, info);
4160                let r = self.build_syn_expr(rhs, info);
4161
4162                // 論理演算子: bool 変換
4163                if matches!(op, BinOp::LogAnd | BinOp::LogOr) {
4164                    let l_str = expr_to_string(&l);
4165                    let r_str = expr_to_string(&r);
4166                    let l_bool = self.wrap_as_bool_condition(lhs, &l_str, info);
4167                    let r_bool = self.wrap_as_bool_condition(rhs, &r_str, info);
4168                    let l_syn: syn::Expr = syn::parse_str(&l_bool).unwrap_or(l);
4169                    let r_syn: syn::Expr = syn::parse_str(&r_bool).unwrap_or(r);
4170                    return syn::Expr::Binary(syn::ExprBinary {
4171                        attrs: vec![], left: Box::new(l_syn),
4172                        op: crate::syn_codegen::to_syn_binop(*op),
4173                        right: Box::new(r_syn),
4174                    });
4175                }
4176
4177                // 型キャスト挿入(整数幅、bool→int、float↔int、enum→int)
4178                let lt = self.infer_expr_type_unified(lhs, info);
4179                let rt = self.infer_expr_type_unified(rhs, info);
4180
4181                // 片側だけ判定可能でも enum は必ず integer にキャストする。
4182                // `cs << 7` のように rhs が IntLit Binary で型推論 None の
4183                // ケースを拾う(enum 単独で Shl/BitOr 等が定義されていない)。
4184                let make_binary_op = |left: syn::Expr, right: syn::Expr| -> syn::Expr {
4185                    syn::Expr::Binary(syn::ExprBinary {
4186                        attrs: vec![], left: Box::new(left),
4187                        op: crate::syn_codegen::to_syn_binop(*op),
4188                        right: Box::new(right),
4189                    })
4190                };
4191                match (&lt, &rt) {
4192                    (Some(lut), None) if self.is_rust_enum_type(lut) => {
4193                        return make_binary_op(cast_syn_expr(l, "u32"), r);
4194                    }
4195                    (None, Some(rut)) if self.is_rust_enum_type(rut) => {
4196                        return make_binary_op(l, cast_syn_expr(r, "u32"));
4197                    }
4198                    _ => {}
4199                }
4200
4201                if let (Some(lut), Some(rut)) = (&lt, &rt) {
4202                    let make_binary = |left: syn::Expr, right: syn::Expr| -> syn::Expr {
4203                        syn::Expr::Binary(syn::ExprBinary {
4204                            attrs: vec![], left: Box::new(left),
4205                            op: crate::syn_codegen::to_syn_binop(*op),
4206                            right: Box::new(right),
4207                        })
4208                    };
4209                    // enum → integer キャスト(C 側は int 互換だが Rust enum は
4210                    // nominal 型なので比較・ビット演算で `as <int>` が必要)
4211                    let l_is_enum = self.is_rust_enum_type(lut);
4212                    let r_is_enum = self.is_rust_enum_type(rut);
4213                    if l_is_enum && !r_is_enum {
4214                        let rs = rut.to_rust_string();
4215                        let target = normalize_integer_type(&rs).unwrap_or("u32");
4216                        return make_binary(cast_syn_expr(l, target), r);
4217                    }
4218                    if r_is_enum && !l_is_enum {
4219                        let ls = lut.to_rust_string();
4220                        let target = normalize_integer_type(&ls).unwrap_or("u32");
4221                        return make_binary(l, cast_syn_expr(r, target));
4222                    }
4223                    // bool → integer キャスト
4224                    if rut.is_bool() {
4225                        let ls = lut.to_rust_string();
4226                        if let Some(nl) = normalize_integer_type(&ls) {
4227                            return make_binary(l, cast_syn_expr(r, nl));
4228                        }
4229                    }
4230                    if lut.is_bool() {
4231                        let rs = rut.to_rust_string();
4232                        if let Some(nr) = normalize_integer_type(&rs) {
4233                            return make_binary(cast_syn_expr(l, nr), r);
4234                        }
4235                    }
4236                    // float ↔ integer キャスト
4237                    if lut.is_float() && !rut.is_float() {
4238                        let ls = lut.to_rust_string();
4239                        let float_ty = if ls == "c_float" || ls == "f32" { "f32" } else { "f64" };
4240                        return make_binary(l, cast_syn_expr(r, float_ty));
4241                    }
4242                    if rut.is_float() && !lut.is_float() {
4243                        let rs = rut.to_rust_string();
4244                        let float_ty = if rs == "c_float" || rs == "f32" { "f32" } else { "f64" };
4245                        return make_binary(cast_syn_expr(l, float_ty), r);
4246                    }
4247                    // 整数幅不一致 → wider type にキャスト
4248                    let ls = lut.to_rust_string();
4249                    let rs = rut.to_rust_string();
4250                    if let Some(wider) = wider_integer_type(&ls, &rs) {
4251                        if normalize_integer_type(&ls) != Some(wider) {
4252                            return make_binary(cast_syn_expr(l, wider), r);
4253                        } else {
4254                            return make_binary(l, cast_syn_expr(r, wider));
4255                        }
4256                    }
4257                }
4258                // float (片方のみ型判明)
4259                {
4260                    let make_binary = |left: syn::Expr, right: syn::Expr| -> syn::Expr {
4261                        syn::Expr::Binary(syn::ExprBinary {
4262                            attrs: vec![], left: Box::new(left),
4263                            op: crate::syn_codegen::to_syn_binop(*op),
4264                            right: Box::new(right),
4265                        })
4266                    };
4267                    match (&lt, &rt) {
4268                        (Some(lut), None) if lut.is_float() => {
4269                            let ls = lut.to_rust_string();
4270                            let float_ty = if ls == "c_float" || ls == "f32" { "f32" } else { "f64" };
4271                            return make_binary(l, cast_syn_expr(r, float_ty));
4272                        }
4273                        (None, Some(rut)) if rut.is_float() => {
4274                            let rs = rut.to_rust_string();
4275                            let float_ty = if rs == "c_float" || rs == "f32" { "f32" } else { "f64" };
4276                            return make_binary(cast_syn_expr(l, float_ty), r);
4277                        }
4278                        _ => {}
4279                    }
4280                    // ビット演算で片方のみ型判明
4281                    if matches!(op, BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor) {
4282                        match (&lt, &rt) {
4283                            (Some(lut), None) => {
4284                                let ls = lut.to_rust_string();
4285                                if let Some(nl) = normalize_integer_type(&ls) {
4286                                    return make_binary(l, cast_syn_expr(r, nl));
4287                                }
4288                            }
4289                            (None, Some(rut)) => {
4290                                let rs = rut.to_rust_string();
4291                                if let Some(nr) = normalize_integer_type(&rs) {
4292                                    return make_binary(cast_syn_expr(l, nr), r);
4293                                }
4294                            }
4295                            _ => {}
4296                        }
4297                    }
4298                }
4299                // 基本の二項演算
4300                syn::Expr::Binary(syn::ExprBinary {
4301                    attrs: vec![],
4302                    left: Box::new(l),
4303                    op: crate::syn_codegen::to_syn_binop(*op),
4304                    right: Box::new(r),
4305                })
4306            }
4307            ExprKind::Call { func, args } => {
4308                // 共通フィールドマクロが定義する関数ポインタフィールドの呼び出しを検出。
4309                // `(*x).xcv_root_u.xcv_xsub(args)` のような Member/PtrMember 経由の Call で、
4310                // canonical type が fn ポインタなら `<field>.unwrap_unchecked()(args)` 形式で出力。
4311                if let Some(syn_call) = self.try_build_common_macro_fn_call(func, args, info) {
4312                    return syn_call;
4313                }
4314                // builtin 関数の特殊処理
4315                if let ExprKind::Ident(name) = &func.kind {
4316                    let func_name = self.interner.get(*name);
4317                    // __builtin_expect → 引数を透過
4318                    if func_name == "__builtin_expect" && !args.is_empty() {
4319                        return self.build_syn_expr(&args[0], info);
4320                    }
4321                    // __builtin_unreachable → unreachable_unchecked
4322                    if func_name == "__builtin_unreachable" {
4323                        return syn::parse_str("std::hint::unreachable_unchecked()").unwrap();
4324                    }
4325                    // __builtin_ctz/clz → trailing_zeros/leading_zeros
4326                    if (func_name == "__builtin_ctz" || func_name == "__builtin_ctzl") && args.len() == 1 {
4327                        let arg = self.build_syn_expr(&args[0], info);
4328                        return syn::Expr::MethodCall(syn::ExprMethodCall {
4329                            attrs: vec![], receiver: Box::new(arg), dot_token: Default::default(),
4330                            method: ident("trailing_zeros"), turbofish: None,
4331                            paren_token: Default::default(), args: syn::punctuated::Punctuated::new(),
4332                        });
4333                    }
4334                    if (func_name == "__builtin_clz" || func_name == "__builtin_clzl") && args.len() == 1 {
4335                        let arg = self.build_syn_expr(&args[0], info);
4336                        return syn::Expr::MethodCall(syn::ExprMethodCall {
4337                            attrs: vec![], receiver: Box::new(arg), dot_token: Default::default(),
4338                            method: ident("leading_zeros"), turbofish: None,
4339                            paren_token: Default::default(), args: syn::punctuated::Punctuated::new(),
4340                        });
4341                    }
4342                    // ASSERT_IS_LITERAL 等 → 引数を透過
4343                    if matches!(func_name, "ASSERT_IS_LITERAL" | "ASSERT_IS_PTR" | "ASSERT_NOT_PTR")
4344                        && args.len() == 1
4345                    {
4346                        return self.build_syn_expr(&args[0], info);
4347                    }
4348                    // offsetof → std::mem::offset_of!
4349                    //
4350                    // args[0] は本来 BuiltinCall arm で TypeName として処理される。
4351                    // ここに来るのは offsetof が通常の関数呼び出しとしてパースされた
4352                    // ケースで、args[0] は型名を表す Ident になる。build_syn_expr の
4353                    // Ident arm は known_symbols にない名前を unresolved_names に
4354                    // 登録してしまい、cascade 連鎖で依存先まで TYPE_INCOMPLETE 化する。
4355                    // 型名の Ident は名前そのものを使えば十分なので bypass する。
4356                    if matches!(func_name, "offsetof" | "__builtin_offsetof") && args.len() == 2 {
4357                        let type_name_str = if let ExprKind::Ident(name) = &args[0].kind {
4358                            escape_rust_keyword(self.interner.get(*name)).to_string()
4359                        } else {
4360                            let s = self.build_syn_expr(&args[0], info);
4361                            expr_to_string(&s)
4362                        };
4363                        if let Some(field_path) = self.expr_to_field_path(&args[1]) {
4364                            return syn::parse_str(&format!("std::mem::offset_of!({}, {})", type_name_str, field_path))
4365                                .unwrap_or_else(|_| int_lit(0));
4366                        }
4367                    }
4368                }
4369
4370                // 関数名を構築
4371                let f_syn = self.build_syn_expr(func, info);
4372                let f_str = expr_to_string(&f_syn);
4373
4374                let callee_name = if let ExprKind::Ident(name) = &func.kind { Some(*name) } else { None };
4375                let needs_my_perl = callee_name
4376                    .map(|name| self.needs_my_perl_for_call(name, args.len()))
4377                    .unwrap_or(false);
4378
4379                // ジェネリック型パラメータのチェック
4380                let callee_generics = callee_name
4381                    .and_then(|name| self.get_callee_generic_params(name).cloned());
4382
4383                if let Some(ref generics) = callee_generics {
4384                    // turbofish 構文 — 文字列ベースで構築(型引数のため)
4385                    let mut type_args = Vec::new();
4386                    let mut value_args: Vec<String> = if needs_my_perl {
4387                        vec!["my_perl".to_string()]
4388                    } else { vec![] };
4389                    let mut value_idx = if needs_my_perl { 1usize } else { 0 };
4390                    for (i, arg) in args.iter().enumerate() {
4391                        if generics.contains_key(&(i as i32)) {
4392                            let syn_arg = self.build_syn_expr(arg, info);
4393                            type_args.push(normalize_parens(&expr_to_string(&syn_arg)));
4394                        } else {
4395                            value_args.push(self.build_arg_string_unified(arg, info, callee_name, value_idx));
4396                            value_idx += 1;
4397                        }
4398                    }
4399                    return syn::parse_str(&format!("{}::<{}>({})", f_str, type_args.join(", "), value_args.join(", ")))
4400                        .unwrap_or_else(|_| int_lit(0));
4401                }
4402
4403                // 通常の関数呼び出し — 引数を処理(統一版)
4404                let mut arg_strs: Vec<String> = if needs_my_perl {
4405                    vec!["my_perl".to_string()]
4406                } else { vec![] };
4407                let arg_offset = if needs_my_perl { 1usize } else { 0 };
4408                for (i, arg) in args.iter().enumerate() {
4409                    arg_strs.push(self.build_arg_string_unified(arg, info, callee_name, i + arg_offset));
4410                }
4411                syn::parse_str(&format!("{}({})", f_str, arg_strs.join(", ")))
4412                    .unwrap_or_else(|_| int_lit(0))
4413            }
4414            ExprKind::MacroCall { name, args, expanded, .. } => {
4415                if self.should_emit_as_macro_call(*name) {
4416                    let name_str = escape_rust_keyword(self.interner.get(*name));
4417                    let needs_my_perl = self.needs_my_perl_for_call(*name, args.len());
4418                    let mut a: Vec<String> = if needs_my_perl {
4419                        vec!["my_perl".to_string()]
4420                    } else { vec![] };
4421                    for arg in args {
4422                        let arg_str = expr_to_string(&self.build_syn_expr(arg, info));
4423                        a.push(normalize_parens(&arg_str));
4424                    }
4425                    syn::parse_str(&format!("{}({})", name_str, a.join(", ")))
4426                        .unwrap_or_else(|_| int_lit(0))
4427                } else {
4428                    self.build_syn_expr(expanded, info)
4429                }
4430            }
4431            ExprKind::BuiltinCall { name, args } => {
4432                let func_name = self.interner.get(*name);
4433                if matches!(func_name, "offsetof" | "__builtin_offsetof" | "STRUCT_OFFSET")
4434                    && args.len() == 2
4435                {
4436                    let type_str = match &args[0] {
4437                        crate::ast::BuiltinArg::TypeName(tn) => self.type_name_to_rust(tn),
4438                        crate::ast::BuiltinArg::Expr(e) => {
4439                            let s = self.build_syn_expr(e, info);
4440                            expr_to_string(&s)
4441                        }
4442                    };
4443                    let field_expr = match &args[1] {
4444                        crate::ast::BuiltinArg::Expr(e) => self.expr_to_field_path(e),
4445                        _ => None,
4446                    };
4447                    if let Some(fp) = field_expr {
4448                        return syn::parse_str(&format!("std::mem::offset_of!({}, {})", type_str, fp))
4449                            .unwrap_or_else(|_| int_lit(0));
4450                    }
4451                }
4452                // フォールバック: 通常の関数呼び出し
4453                let a: Vec<String> = args.iter().map(|arg| match arg {
4454                    crate::ast::BuiltinArg::Expr(e) => {
4455                        let s = self.build_syn_expr(e, info);
4456                        expr_to_string(&s)
4457                    }
4458                    crate::ast::BuiltinArg::TypeName(tn) => self.type_name_to_rust(tn),
4459                }).collect();
4460                syn::parse_str(&format!("{}({})", func_name, a.join(", ")))
4461                    .unwrap_or_else(|_| int_lit(0))
4462            }
4463            ExprKind::Assign { op, lhs, rhs } => {
4464                self.build_assign_syn_expr(*op, lhs, rhs, info)
4465            }
4466            ExprKind::PreInc(inner) => {
4467                self.build_inc_dec_syn_expr(inner, info, /*is_inc=*/ true, /*is_post=*/ false)
4468            }
4469            ExprKind::PreDec(inner) => {
4470                self.build_inc_dec_syn_expr(inner, info, /*is_inc=*/ false, /*is_post=*/ false)
4471            }
4472            ExprKind::PostInc(inner) => {
4473                self.build_inc_dec_syn_expr(inner, info, /*is_inc=*/ true, /*is_post=*/ true)
4474            }
4475            ExprKind::PostDec(inner) => {
4476                self.build_inc_dec_syn_expr(inner, info, /*is_inc=*/ false, /*is_post=*/ true)
4477            }
4478            ExprKind::Assert { kind, condition } => {
4479                let assert_str = if let Some((real_cond, msg)) = decompose_assert_with_message(condition) {
4480                    let c = self.build_syn_expr(real_cond, info);
4481                    let c_str = expr_to_string(&c);
4482                    let cond_str = self.wrap_as_bool_condition(real_cond, &c_str, info);
4483                    format!("assert!({}, \"{}\")", normalize_parens(&cond_str), msg)
4484                } else {
4485                    let c = self.build_syn_expr(condition, info);
4486                    let c_str = expr_to_string(&c);
4487                    if is_boolean_expr(condition) || self.is_bool_expr_with_dict(condition) {
4488                        format!("assert!({})", normalize_parens(&c_str))
4489                    } else if self.is_pointer_expr_unified(condition, info)
4490                        || self.infer_expr_type_unified(condition, info).is_some_and(|ut| ut.is_pointer()) {
4491                        // `.is_null()` をくっつける際は受け手側を括弧で囲む。
4492                        // c_str が `*x` のような単項式の場合 `!*x.is_null()` が
4493                        // `!*(x.is_null())` と解釈されるため。
4494                        format!("assert!(!({}).is_null())", c_str)
4495                    } else {
4496                        format!("assert!({} != 0)", normalize_parens(&c_str))
4497                    }
4498                };
4499                let result = match kind {
4500                    AssertKind::Assert => assert_str,
4501                    AssertKind::AssertUnderscore => format!("{{ {}; }}", assert_str),
4502                };
4503                syn::parse_str(&result).unwrap_or_else(|_| int_lit(0))
4504            }
4505            ExprKind::StmtExpr(compound) => {
4506                // MUTABLE_PTR パターン → 内部式に変換
4507                if let Some(init_expr) = self.detect_mutable_ptr_pattern(compound) {
4508                    return self.build_syn_expr(init_expr, info);
4509                }
4510                // 通常の statement expression: Rust のブロック式として出力。
4511                // 旧パスの実装と同じ部分文字列構築 + syn::parse_str だが、
4512                // 内部の式は build_expr_string (build_syn_expr 経由) を通る。
4513                let mut parts: Vec<String> = Vec::new();
4514                for item in &compound.items {
4515                    match item {
4516                        BlockItem::Stmt(Stmt::Expr(Some(e), _)) => {
4517                            parts.push(self.build_expr_string(e, info));
4518                        }
4519                        BlockItem::Stmt(stmt) => {
4520                            let s = match info {
4521                                Some(info) => self.stmt_to_rust(stmt, info),
4522                                None => self.stmt_to_rust_inline(stmt, ""),
4523                            };
4524                            parts.push(s);
4525                        }
4526                        BlockItem::Decl(decl) => {
4527                            self.collect_decl_types(decl);
4528                            let decl_str = self.decl_to_rust_let(decl, "");
4529                            for line in decl_str.lines() {
4530                                let trimmed = line.trim();
4531                                if !trimmed.is_empty() {
4532                                    parts.push(trimmed.strip_suffix(';').unwrap_or(trimmed).to_string());
4533                                }
4534                            }
4535                        }
4536                    }
4537                }
4538                let block_str = if parts.is_empty() {
4539                    "{ }".to_string()
4540                } else if parts.len() == 1 {
4541                    parts.pop().unwrap()
4542                } else {
4543                    let last = parts.pop().unwrap();
4544                    let stmts = parts.join("; ");
4545                    format!("{{ {}; {} }}", stmts, last)
4546                };
4547                syn::parse_str(&block_str).unwrap_or_else(|_| int_lit(0))
4548            }
4549            ExprKind::Alignof(ty) => {
4550                let ty_str = self.type_name_to_rust(ty);
4551                syn::parse_str(&format!("std::mem::align_of::<{}>()", ty_str))
4552                    .unwrap_or_else(|_| int_lit(0))
4553            }
4554            // CompoundLit / 未対応バリアント: 0 を返してエラーを記録。
4555            // 旧パスでも `/* TODO */` マーカーで生成コードが壊れる挙動だったため、
4556            // 体感的には同等。実用上 macro_bindings.rs にはほぼ現れない。
4557            _ => {
4558                self.codegen_errors.push(format!(
4559                    "unhandled ExprKind in syn codegen: {:?}",
4560                    std::mem::discriminant(&expr.kind)
4561                ));
4562                int_lit(0)
4563            }
4564        }
4565    }
4566
4567    /// 関数引数を文字列に変換(macro/inline 統一版)
4568    ///
4569    /// expr_to_rust_arg 相当の処理を build_syn_expr ベースで行う。
4570    fn build_arg_string_unified(&mut self, arg: &Expr, info: Option<&MacroInferInfo>,
4571                                  callee: Option<InternedStr>, arg_index: usize) -> String {
4572        // macro: literal string パラメータ変換
4573        if info.is_some() {
4574            if let Some(name) = self.find_literal_string_ident(arg) {
4575                if let Some(callee_name) = callee {
4576                    if self.callee_expects_literal_string(callee_name, arg_index) {
4577                        return escape_rust_keyword(self.interner.get(*name));
4578                    }
4579                }
4580                let param = escape_rust_keyword(self.interner.get(*name));
4581                return format!("{}.as_ptr() as *const c_char", param);
4582            }
4583        }
4584        // null pointer 変換
4585        if is_null_literal(arg) {
4586            if let Some(callee_name) = callee {
4587                let func_name = self.interner.get(callee_name).to_string();
4588                if let Some(expected_ut) = self.get_callee_param_type_extended(&func_name, arg_index) {
4589                    if expected_ut.is_pointer() {
4590                        return null_ptr_expr(&expected_ut);
4591                    }
4592                }
4593            }
4594        }
4595        // bool パラメータ変換
4596        if let Some(callee_name) = callee {
4597            let func_name = self.interner.get(callee_name);
4598            if self.callee_param_is_bool(func_name, arg_index) {
4599                match &arg.kind {
4600                    ExprKind::IntLit(0) => return "false".to_string(),
4601                    ExprKind::IntLit(1) => return "true".to_string(),
4602                    _ => {}
4603                }
4604            }
4605        }
4606        // 式の生成
4607        let mut syn_expr = self.build_syn_expr(arg, info);
4608        // 整数幅キャスト / SV subtype キャストを syn レベルで挿入
4609        // (文字列 "as type" の優先順位崩壊を防止)
4610        if let Some(callee_name) = callee {
4611            let func_name = self.interner.get(callee_name).to_string();
4612            if let Some(expected_ut) = self.get_callee_param_type_extended(&func_name, arg_index) {
4613                let actual_ut = self.infer_expr_type_unified(arg, info);
4614                let actual_ty = actual_ut.as_ref().map(|ut| ut.to_rust_string());
4615                let expected_ty = expected_ut.to_rust_string();
4616                // C 文字列リテラル (`c"..."`, &CStr 型) を callee の `*const c_char` 等
4617                // に変換する際に `.as_ptr()` を付加。これを忘れると
4618                // `expected *const i8, found &CStr` エラーになる。
4619                if matches!(&arg.kind, ExprKind::StringLit(_))
4620                    && expected_ut.is_pointer()
4621                {
4622                    syn_expr = crate::syn_codegen::method_call(syn_expr, "as_ptr", vec![]);
4623                }
4624                syn_expr = self.cast_arg_syn_if_needed(syn_expr, actual_ty.as_deref(), &expected_ty);
4625            }
4626        }
4627        normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr))
4628    }
4629
4630    /// 引数のキャスト挿入を syn::Expr レベルで実施。
4631    /// 旧パスの `cast_integer_arg_if_needed` (文字列ベース) と論理は同等だが、
4632    /// `as` 演算子の優先順位崩壊を起こさない。
4633    fn cast_arg_syn_if_needed(&self, arg_expr: syn::Expr,
4634                              actual_ty: Option<&str>, expected_ty: &str) -> syn::Expr {
4635        use crate::syn_codegen::cast_syn_expr;
4636        if let Some(actual) = actual_ty {
4637            // enum → integer キャスト(actual が Rust enum で expected が整数型)
4638            let actual_ut = UnifiedType::from_rust_str(actual);
4639            if self.is_rust_enum_type(&actual_ut) {
4640                if let Some(target) = normalize_integer_type(expected_ty) {
4641                    return cast_syn_expr(arg_expr, target);
4642                }
4643            }
4644            let na = normalize_integer_type(actual);
4645            let ne = normalize_integer_type(expected_ty);
4646            if let (Some(a), Some(e)) = (na, ne) {
4647                if !integer_types_compatible(a, e) {
4648                    return cast_syn_expr(arg_expr, e);
4649                }
4650                return arg_expr;
4651            }
4652            // ポインタ型のサブタイプ変換 (e.g., *mut GV → *mut SV)
4653            if actual != expected_ty {
4654                let actual_ut = UnifiedType::from_rust_str(actual);
4655                let expected_ut = UnifiedType::from_rust_str(expected_ty);
4656                if actual_ut.is_pointer() && expected_ut.is_pointer()
4657                    && is_sv_subtype_cast(&actual_ut, &expected_ut) {
4658                    let cast_ty = if actual.contains("*const") {
4659                        expected_ty.replace("*mut", "*const")
4660                    } else {
4661                        expected_ty.to_string()
4662                    };
4663                    return cast_syn_expr(arg_expr, &cast_ty);
4664                }
4665                // `*mut c_void` 受け取り: libc の memset/memcpy/memcmp 等は
4666                // `*mut c_void` / `*const c_void` を取るが、呼出側は
4667                // `*mut c_char` や `*mut T` を渡すことが多い。raw pointer
4668                // の as-cast はいつでも合法なので、void pointer への変換を
4669                // 汎用的に許可する。
4670                if actual_ut.is_pointer() && expected_ut.is_pointer()
4671                    && expected_ut.is_void_pointer()
4672                {
4673                    return cast_syn_expr(arg_expr, expected_ty);
4674                }
4675                // const/mut のみ違い、または inner 別名違い(c_char≡i8 等)
4676                // の自動キャスト。Rust は単一レベルの `*mut T → *const T` を
4677                // 自動強制するため、その場合だけ cast を挿入しない。
4678                // ネストした二重ポインタの const 違い(例: `*mut *mut T`
4679                // → `*mut *const T`)は強制されないので cast が必要。
4680                if pointer_inner_compatible(&actual_ut, &expected_ut) {
4681                    let top_mut_to_const = !actual_ut.is_const_pointer()
4682                        && expected_ut.is_const_pointer();
4683                    let top_const_same = actual_ut.is_const_pointer()
4684                        == expected_ut.is_const_pointer();
4685                    // 内側まで完全一致(文字列レベル)か
4686                    let inner_exact_match = actual_ut.inner_type()
4687                        .zip(expected_ut.inner_type())
4688                        .is_some_and(|(a, b)| a.to_rust_string() == b.to_rust_string());
4689                    let auto_coerces = (top_mut_to_const || top_const_same)
4690                        && inner_exact_match;
4691                    if !auto_coerces {
4692                        return cast_syn_expr(arg_expr, expected_ty);
4693                    }
4694                }
4695            }
4696            return arg_expr;
4697        }
4698        // actual 不明 + expected が SV ポインタ → 関数呼び出し風なら as キャスト
4699        let expected_ut = UnifiedType::from_rust_str(expected_ty);
4700        if expected_ut.is_pointer() {
4701            if let Some(inner) = expected_ut.inner_type() {
4702                if let UnifiedType::Named(name) = inner {
4703                    let n = name.as_str();
4704                    if matches!(n, "SV" | "GV" | "HV" | "AV" | "CV" | "IO") {
4705                        if matches!(&arg_expr, syn::Expr::Call(_) | syn::Expr::MethodCall(_)) {
4706                            return cast_syn_expr(arg_expr, expected_ty);
4707                        }
4708                    }
4709                }
4710            }
4711        }
4712        arg_expr
4713    }
4714
4715    /// 関数ポインタフィールド呼び出しを検出し、
4716    /// `<receiver>.<field>.unwrap_unchecked()(args)` 形式の `syn::Expr` を構築する。
4717    ///
4718    /// `_XPVCV_COMMON` の `xcv_xsub` や `PerlInterpreter` の `Ilockhook` のような
4719    /// `Option<unsafe extern "C" fn(...)>` フィールドを呼び出すパターンに対応する。
4720    /// 検出条件:
4721    ///
4722    /// 1. callee が `Member` または `PtrMember` アクセスである
4723    /// 2. そのフィールドが「関数ポインタ」と判定できる
4724    ///    - 第一に共通フィールドマクロ(`_XPVCV_COMMON` 等)由来の canonical
4725    ///      type で判定(C ソース由来)
4726    ///    - フォールバックとして bindings.rs 由来の `field_type_map` で判定
4727    ///      (文字列ヒューリスティク: `fn(` を含む)
4728    ///
4729    /// 当てはまらなければ `None` を返し、呼び出し側は通常の Call 生成パスへ進む。
4730    fn try_build_common_macro_fn_call(
4731        &mut self,
4732        func: &Expr,
4733        args: &[Expr],
4734        info: Option<&MacroInferInfo>,
4735    ) -> Option<syn::Expr> {
4736        use crate::syn_codegen::*;
4737
4738        let member_id = match &func.kind {
4739            ExprKind::Member { member, .. } | ExprKind::PtrMember { member, .. } => *member,
4740            _ => return None,
4741        };
4742
4743        // 第一: 共通フィールドマクロ由来の canonical type で判定
4744        let mut is_fn_ptr = self
4745            .fields_dict
4746            .and_then(|d| d.canonical_field(member_id).map(|(_, f)| f.is_fn_pointer))
4747            .unwrap_or(false);
4748
4749        // フォールバック: bindings.rs 側の型を見て fn(...) 形式なら fn ポインタとみなす。
4750        // bindgen 出力では Option<unsafe extern "C" fn(...)> 形式になるため
4751        // "fn(" を含むかでヒューリスティック判定。フィールドの直接の型が
4752        // typedef(例: `share_proc_t`)の場合は RustDeclDict.types で解決する。
4753        if !is_fn_ptr {
4754            let field_name = self.interner.get(member_id);
4755            if let Some(ut) = self.field_type_map.get(field_name) {
4756                let ty_str = ut.to_rust_string();
4757                if type_str_is_fn_pointer(&ty_str) {
4758                    is_fn_ptr = true;
4759                } else if let Some(dict) = self.rust_decl_dict {
4760                    if let Some(alias) = dict.types.get(&ty_str) {
4761                        if type_str_is_fn_pointer(&alias.ty) {
4762                            is_fn_ptr = true;
4763                        }
4764                    }
4765                }
4766            }
4767        }
4768
4769        if !is_fn_ptr {
4770            return None;
4771        }
4772
4773        // <receiver>.<field> までを syn::Expr で組む
4774        let field_access = self.build_syn_expr(func, info);
4775        // .unwrap_unchecked() を挟む(bindgen の Option<fn> をはがす)
4776        let callee = method_call(field_access, "unwrap_unchecked", vec![]);
4777
4778        // 引数: 既存ヘルパで構築(callee 名なし → 型ベース cast は無効)
4779        let mut punctuated = syn::punctuated::Punctuated::new();
4780        for (i, arg) in args.iter().enumerate() {
4781            let s = self.build_arg_string_unified(arg, info, None, i);
4782            let parsed = syn::parse_str(&s).unwrap_or_else(|_| int_lit(0));
4783            punctuated.push(parsed);
4784        }
4785
4786        Some(syn::Expr::Call(syn::ExprCall {
4787            attrs: vec![],
4788            func: Box::new(callee),
4789            paren_token: Default::default(),
4790            args: punctuated,
4791        }))
4792    }
4793
4794    /// lvalue 用の syn::Expr を構築(MacroCall/Call の展開対応)
4795    fn build_lvalue_syn_expr(&mut self, expr: &Expr, info: Option<&MacroInferInfo>) -> syn::Expr {
4796        if let ExprKind::MacroCall { expanded, .. } = &expr.kind {
4797            return self.build_syn_expr(expanded, info);
4798        }
4799        if let ExprKind::Call { func, args } = &expr.kind {
4800            if let Some(expanded) = self.try_expand_call_as_lvalue_syn(func, args, info) {
4801                return expanded;
4802            }
4803            let syn_expr = self.build_syn_expr(expr, info);
4804            let s = crate::syn_codegen::expr_to_string(&syn_expr);
4805            self.codegen_errors.push(format!("invalid lvalue: {} cannot be assigned to", s));
4806            return syn_expr;
4807        }
4808        self.build_syn_expr(expr, info)
4809    }
4810
4811    /// `Pre/PostInc/Dec` を syn::Expr で構築。
4812    /// 旧パス `expr_to_rust_ctx` の対応 arm(rust_codegen.rs の PreInc 〜 PostDec)と同等。
4813    fn build_inc_dec_syn_expr(&mut self, inner: &Expr, info: Option<&MacroInferInfo>,
4814                              is_inc: bool, is_post: bool) -> syn::Expr {
4815        use crate::syn_codegen::*;
4816        let lv = self.build_lvalue_syn_expr(inner, info);
4817        let is_ptr = self.is_pointer_expr_unified(inner, info)
4818            || self.infer_expr_type_unified(inner, info).is_some_and(|ut| ut.is_pointer());
4819        // 「lv を 1 つ増減する」文を構築
4820        let step_stmt: syn::Stmt = if is_ptr {
4821            // lv = lv.wrapping_add(1);  または wrapping_sub
4822            let method = if is_inc { "wrapping_add" } else { "wrapping_sub" };
4823            let call = method_call(lv.clone(), method, vec![int_lit(1)]);
4824            semi_stmt(assign_expr(lv.clone(), call))
4825        } else {
4826            let op = if is_inc {
4827                syn::BinOp::AddAssign(Default::default())
4828            } else {
4829                syn::BinOp::SubAssign(Default::default())
4830            };
4831            semi_stmt(assign_op_expr(lv.clone(), op, int_lit(1)))
4832        };
4833        if is_post {
4834            // { let _t = lv; <step>; _t }
4835            let save = let_stmt("_t", lv.clone());
4836            block_with_value(vec![save, step_stmt], ident_expr("_t"))
4837        } else {
4838            // { <step>; lv }
4839            block_with_value(vec![step_stmt], lv)
4840        }
4841    }
4842
4843    /// `Assign` を syn::Expr で構築。
4844    /// 旧パス `expr_to_rust_ctx` の Assign arm(rust_codegen.rs:4380 周辺)と同等。
4845    fn build_assign_syn_expr(&mut self, op: AssignOp, lhs: &Expr, rhs: &Expr,
4846                             info: Option<&MacroInferInfo>) -> syn::Expr {
4847        use crate::syn_codegen::*;
4848        let l = self.build_lvalue_syn_expr(lhs, info);
4849        let lhs_ut = self.infer_expr_type_unified(lhs, info);
4850
4851        // RHS の構築(null リテラル特別扱い + プレーン Assign の整数幅キャスト)
4852        let r: syn::Expr = if is_null_literal(rhs) && op == AssignOp::Assign {
4853            match &lhs_ut {
4854                Some(lut) if lut.is_pointer() => {
4855                    if lut.is_const_pointer() {
4856                        syn::parse_str("std::ptr::null()").unwrap_or_else(|_| int_lit(0))
4857                    } else {
4858                        syn::parse_str("std::ptr::null_mut()").unwrap_or_else(|_| int_lit(0))
4859                    }
4860                }
4861                Some(_) => int_lit(0),
4862                None => syn::parse_str("std::ptr::null_mut()").unwrap_or_else(|_| int_lit(0)),
4863            }
4864        } else {
4865            let mut r_expr = self.build_syn_expr(rhs, info);
4866            // プレーン Assign のみ: LHS 型に合わせて整数幅キャスト挿入
4867            if op == AssignOp::Assign {
4868                // 整数リテラル 0/1 を float LHS に代入 → `0.0` / `1.0` に変換
4869                if let Some(ref lut) = lhs_ut {
4870                    if lut.is_float() {
4871                        if let ExprKind::IntLit(n) = &rhs.kind {
4872                            r_expr = syn::parse_str(&format!("{}.0", n))
4873                                .unwrap_or_else(|_| int_lit(0));
4874                        }
4875                    }
4876                }
4877                if let Some(ref lut) = lhs_ut {
4878                    if let Some(rut) = self.infer_expr_type_unified(rhs, info) {
4879                        let ls = lut.to_rust_string();
4880                        let rs = rut.to_rust_string();
4881                        if let (Some(nl), Some(nr)) = (
4882                            normalize_integer_type(&ls),
4883                            normalize_integer_type(&rs),
4884                        ) {
4885                            if !integer_types_compatible(nl, nr) {
4886                                r_expr = cast_syn_expr(r_expr, nl);
4887                            }
4888                        }
4889                        // ポインタ const/mut 不一致 → LHS 型に明示キャスト
4890                        else if lut.is_pointer() && rut.is_pointer()
4891                            && lut.is_const_pointer() != rut.is_const_pointer()
4892                        {
4893                            r_expr = cast_syn_expr(r_expr, &ls);
4894                        }
4895                        // SV サブタイプ / void ポインタ間の変換
4896                        else if lut.is_pointer() && rut.is_pointer()
4897                            && ls != rs
4898                            && is_sv_subtype_cast(&rut, lut)
4899                        {
4900                            r_expr = cast_syn_expr(r_expr, &ls);
4901                        }
4902                    }
4903                }
4904            }
4905            r_expr
4906        };
4907
4908        // ビットフィールドセッター: LHS が `.getter()` 形式の MethodCall
4909        // (bitfield_methods 由来)だった場合、`set_getter(val)` 呼び出しに
4910        // 書き換える。`a.f() = v` は E0070 (invalid lvalue) になるため。
4911        if op == AssignOp::Assign {
4912            if let syn::Expr::MethodCall(mc) = &l {
4913                if mc.args.is_empty() {
4914                    let method_name = mc.method.to_string();
4915                    if self.is_bitfield_method(&method_name) {
4916                        let setter_name = format!("set_{}", method_name);
4917                        // setter が期待する型 (bitfield getter の戻り値型)
4918                        // に RHS を cast する。bool や違う整数幅で渡される
4919                        // ケースに対応 (`set_op_moresib(bool)` 等の E0308)。
4920                        let arg_val = if let Some(dict) = self.rust_decl_dict {
4921                            // bitfield_method_types: (struct, method) → ret_ty
4922                            // struct 名が不明なケースは任意の一致で決める
4923                            let ret_ty = dict.bitfield_method_types.iter()
4924                                .find(|((_, m), _)| m == &method_name)
4925                                .map(|(_, ty)| ty.clone());
4926                            if let Some(ty) = ret_ty {
4927                                cast_syn_expr(r, &ty)
4928                            } else {
4929                                r
4930                            }
4931                        } else {
4932                            r
4933                        };
4934                        let setter_call = method_call(
4935                            (*mc.receiver).clone(),
4936                            &setter_name,
4937                            vec![arg_val],
4938                        );
4939                        let stmt = semi_stmt(setter_call);
4940                        return block_with_value(vec![stmt], l);
4941                    }
4942                }
4943            }
4944        }
4945
4946        // op に応じた文を構築し、ブロックでラップ
4947        let stmt: syn::Stmt = match op {
4948            AssignOp::Assign => semi_stmt(assign_expr(l.clone(), r)),
4949            AssignOp::AddAssign | AssignOp::SubAssign => {
4950                let is_ptr = self.is_pointer_expr_unified(lhs, info)
4951                    || lhs_ut.as_ref().is_some_and(|ut| ut.is_pointer());
4952                if is_ptr {
4953                    // lv = lv.wrapping_add(r as usize);
4954                    let method = if op == AssignOp::AddAssign { "wrapping_add" } else { "wrapping_sub" };
4955                    let r_usize = cast_syn_expr(r, "usize");
4956                    let call = method_call(l.clone(), method, vec![r_usize]);
4957                    semi_stmt(assign_expr(l.clone(), call))
4958                } else {
4959                    let syn_op = c_assign_op_to_syn_compound(op).unwrap();
4960                    semi_stmt(assign_op_expr(l.clone(), syn_op, r))
4961                }
4962            }
4963            AssignOp::AndAssign | AssignOp::OrAssign | AssignOp::XorAssign => {
4964                // 整数幅が異なる場合 RHS を LHS 型にキャスト。
4965                // RHS が enum (Named) の場合も LHS 整数型へキャストする
4966                // (Rust enum は nominal 型で `|=` 等が直接働かない)。
4967                let lt = &lhs_ut;
4968                let rt = self.infer_expr_type_unified(rhs, info);
4969                let r_final = {
4970                    let mut casted = false;
4971                    let mut ret = r;
4972                    if let (Some(lut), Some(rut)) = (lt, &rt) {
4973                        let ls = lut.to_rust_string();
4974                        let rs = rut.to_rust_string();
4975                        let nl = normalize_integer_type(&ls);
4976                        let nr = normalize_integer_type(&rs);
4977                        if nl.is_some() && nr.is_some() && nl != nr {
4978                            ret = cast_syn_expr(ret, nl.unwrap());
4979                            casted = true;
4980                        }
4981                        // RHS が enum 型で LHS が整数 → `r as <lhs-int>`
4982                        if !casted && self.is_rust_enum_type(rut) && nl.is_some() {
4983                            ret = cast_syn_expr(ret, nl.unwrap());
4984                            casted = true;
4985                        }
4986                    }
4987                    if !casted {
4988                        if let (Some(lut), None) = (lt, &rt) {
4989                            let ls = lut.to_rust_string();
4990                            if let Some(nl) = normalize_integer_type(&ls) {
4991                                ret = cast_syn_expr(ret, nl);
4992                            }
4993                        }
4994                    }
4995                    ret
4996                };
4997                let syn_op = c_assign_op_to_syn_compound(op).unwrap();
4998                semi_stmt(assign_op_expr(l.clone(), syn_op, r_final))
4999            }
5000            _ => {
5001                let syn_op = c_assign_op_to_syn_compound(op).unwrap();
5002                semi_stmt(assign_op_expr(l.clone(), syn_op, r))
5003            }
5004        };
5005        block_with_value(vec![stmt], l)
5006    }
5007
5008    /// lvalue 用の文字列を構築(`build_lvalue_syn_expr` の文字列化版)
5009    fn build_lvalue_string(&mut self, expr: &Expr, info: Option<&MacroInferInfo>) -> String {
5010        let syn_expr = self.build_lvalue_syn_expr(expr, info);
5011        normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr))
5012    }
5013
5014    /// build_syn_expr + type_hint 適用(generate_macro のトップレベル用)
5015    fn build_syn_expr_with_type_hint(&mut self, expr: &Expr, info: Option<&MacroInferInfo>,
5016                                       type_hint: Option<&str>) -> syn::Expr {
5017        use crate::syn_codegen::*;
5018        if let Some(ty) = type_hint {
5019            let ut = UnifiedType::from_rust_str(ty);
5020            if ut.is_pointer() && is_null_literal(expr) {
5021                return syn::parse_str(&null_ptr_expr(&ut)).unwrap_or_else(|_| int_lit(0));
5022            }
5023            if ut.is_bool() {
5024                match &expr.kind {
5025                    ExprKind::IntLit(0) => return syn::parse_str("false").unwrap(),
5026                    ExprKind::IntLit(1) => return syn::parse_str("true").unwrap(),
5027                    _ => {}
5028                }
5029            }
5030        }
5031        self.build_syn_expr(expr, info)
5032    }
5033
5034    // ================================================================
5035    // 統一文変換 (macro/inline 共通)
5036    // ================================================================
5037
5038    /// return 文を syn::Expr ベースで構築(macro/inline 統一)
5039    ///
5040    /// 整数幅キャストや bool 変換を syn::Expr レベルで挿入することで、
5041    /// 文字列ベースの `(rhs as ty)` フォーマットが `normalize_parens` で
5042    /// 括弧を剥がされて優先順位が崩れる問題(`a & b as u8` 等)を回避する。
5043    fn build_return_stmt(&mut self, expr: &Expr, indent: &str, info: Option<&MacroInferInfo>) -> String {
5044        use crate::syn_codegen::*;
5045        if let Some(ref rt) = self.current_return_type {
5046            if rt.is_pointer() && is_null_literal(expr) {
5047                return format!("{}return {};", indent, null_ptr_expr(rt));
5048            }
5049            if rt.is_bool() {
5050                match &expr.kind {
5051                    ExprKind::IntLit(0) => return format!("{}return false;", indent),
5052                    ExprKind::IntLit(1) => return format!("{}return true;", indent),
5053                    _ => {
5054                        let mut syn_expr = self.build_syn_expr(expr, info);
5055                        if !self.is_bool_expr_with_dict(expr) && !is_bool_syn_expr(&syn_expr) {
5056                            syn_expr = wrap_as_bool(syn_expr);
5057                        }
5058                        let s = normalize_parens(&expr_to_string(&syn_expr));
5059                        return format!("{}return {};", indent, s);
5060                    }
5061                }
5062            }
5063        }
5064        let mut syn_expr = self.build_syn_expr(expr, info);
5065        syn_expr = self.cast_return_syn_expr_if_needed(expr, info, syn_expr);
5066        let s = normalize_parens(&expr_to_string(&syn_expr));
5067        format!("{}return {};", indent, s)
5068    }
5069
5070    /// 返り値式の型キャストを syn::Expr レベルで挿入(必要なら)。
5071    /// `cast_return_expr_if_needed_unified` の syn 版。
5072    fn cast_return_syn_expr_if_needed(&self, expr: &Expr, info: Option<&MacroInferInfo>,
5073                                      syn_expr: syn::Expr) -> syn::Expr {
5074        let Some(ret_ut) = &self.current_return_type else { return syn_expr };
5075        let Some(expr_ut) = self.infer_expr_type_unified(expr, info) else { return syn_expr };
5076        let ret_s = ret_ut.to_rust_string();
5077        let expr_s = expr_ut.to_rust_string();
5078        // enum → integer 戻り値キャスト
5079        if self.is_rust_enum_type(&expr_ut) {
5080            if let Some(nr) = normalize_integer_type(&ret_s) {
5081                return crate::syn_codegen::cast_syn_expr(syn_expr, nr);
5082            }
5083        }
5084        if let (Some(nr), Some(ne)) = (normalize_integer_type(&ret_s), normalize_integer_type(&expr_s)) {
5085            if !integer_types_compatible(nr, ne) {
5086                return crate::syn_codegen::cast_syn_expr(syn_expr, nr);
5087            }
5088        }
5089        // ポインタ戻り値: inner が Rust 上 compatible(c_char≡i8 等)だが文字列
5090        // 表現が違う場合は return 型に合わせて as cast を入れる。
5091        // const/mut 違いも同時に吸収する。
5092        if ret_ut.is_pointer() && expr_ut.is_pointer() && ret_s != expr_s
5093            && pointer_inner_compatible(ret_ut, &expr_ut)
5094        {
5095            return crate::syn_codegen::cast_syn_expr(syn_expr, &ret_s);
5096        }
5097        syn_expr
5098    }
5099
5100    /// 代入文を構築(macro/inline 統一、文コンテキスト用)
5101    ///
5102    /// LHS (`l`) と RHS (`r`) は両方とも syn::Expr 経由でビルドし、
5103    /// 整数幅キャストや `wrapping_add` の `as usize` も `cast_syn_expr` で挿入する。
5104    /// 文字列レベルで `as` を挿入する旧経路は優先順位崩壊を起こすため使わない。
5105    fn build_assign_stmt(&mut self, op: &AssignOp, lhs: &Expr, rhs: &Expr, indent: &str, info: Option<&MacroInferInfo>) -> String {
5106        use crate::syn_codegen::*;
5107        let l = self.build_lvalue_string(lhs, info);
5108        let lhs_ut = self.infer_expr_type_unified(lhs, info);
5109
5110        // RHS の syn::Expr を組み立てる(null リテラル特別扱い + 必要に応じてキャスト)
5111        let r_syn: syn::Expr = if is_null_literal(rhs) && *op == AssignOp::Assign {
5112            match &lhs_ut {
5113                Some(lut) if lut.is_pointer() => {
5114                    let s = if lut.is_const_pointer() { "std::ptr::null()" } else { "std::ptr::null_mut()" };
5115                    syn::parse_str(s).unwrap_or_else(|_| int_lit(0))
5116                }
5117                Some(_) => int_lit(0),
5118                None => syn::parse_str("std::ptr::null_mut()").unwrap_or_else(|_| int_lit(0)),
5119            }
5120        } else {
5121            let mut r_syn = self.build_syn_expr(rhs, info);
5122            // 整数幅キャスト
5123            if *op == AssignOp::Assign {
5124                // 整数リテラル 0/1 を float LHS に代入 → `0.0` / `1.0`
5125                if let Some(ref lut) = lhs_ut {
5126                    if lut.is_float() {
5127                        if let ExprKind::IntLit(n) = &rhs.kind {
5128                            r_syn = syn::parse_str(&format!("{}.0", n))
5129                                .unwrap_or_else(|_| int_lit(0));
5130                        }
5131                    }
5132                }
5133                if let Some(ref lut) = lhs_ut {
5134                    if let Some(rut) = self.infer_expr_type_unified(rhs, info) {
5135                        let ls = lut.to_rust_string();
5136                        let rs = rut.to_rust_string();
5137                        // enum → integer 代入キャスト
5138                        if self.is_rust_enum_type(&rut) {
5139                            if let Some(nl) = normalize_integer_type(&ls) {
5140                                r_syn = cast_syn_expr(r_syn, nl);
5141                            }
5142                        } else if let (Some(nl), Some(nr)) = (normalize_integer_type(&ls), normalize_integer_type(&rs)) {
5143                            // 代入では isize/i64 や usize/u64 を区別する(Rust 的に別型)。
5144                            // integer_types_compatible の緩い判定は演算側で使用。
5145                            if nl != nr {
5146                                r_syn = cast_syn_expr(r_syn, nl);
5147                            }
5148                        }
5149                        // ポインタ const/mut 不一致、あるいは inner 別名違い
5150                        // (c_char≡i8 等の Rust レベル同型)→ LHS 型に明示 cast
5151                        if pointer_const_differs(lut, &rut) {
5152                            r_syn = cast_syn_expr(r_syn, &ls);
5153                        } else if lut.is_pointer() && rut.is_pointer()
5154                            && ls != rs
5155                            && pointer_inner_compatible(lut, &rut)
5156                        {
5157                            r_syn = cast_syn_expr(r_syn, &ls);
5158                        }
5159                        // SV サブタイプ / void ポインタ間の変換
5160                        // (*sv_).sv_any = <XPVIV *> を受け入れるため)
5161                        else if lut.is_pointer() && rut.is_pointer()
5162                            && ls != rs
5163                            && is_sv_subtype_cast(&rut, lut)
5164                        {
5165                            r_syn = cast_syn_expr(r_syn, &ls);
5166                        }
5167                    }
5168                }
5169            } else if matches!(op, AssignOp::AndAssign | AssignOp::OrAssign | AssignOp::XorAssign) {
5170                let rt = self.infer_expr_type_unified(rhs, info);
5171                if let (Some(lut), Some(rut)) = (&lhs_ut, &rt) {
5172                    let ls = lut.to_rust_string();
5173                    let rs = rut.to_rust_string();
5174                    let nl = normalize_integer_type(&ls);
5175                    let nr = normalize_integer_type(&rs);
5176                    if nl.is_some() && nr.is_some() && nl != nr {
5177                        r_syn = cast_syn_expr(r_syn, nl.unwrap());
5178                    } else if self.is_rust_enum_type(rut) && nl.is_some() {
5179                        // RHS が enum で LHS が整数 → `r as <lhs-int>`
5180                        r_syn = cast_syn_expr(r_syn, nl.unwrap());
5181                    }
5182                } else if let (Some(lut), None) = (&lhs_ut, &rt) {
5183                    let ls = lut.to_rust_string();
5184                    if let Some(nl) = normalize_integer_type(&ls) {
5185                        r_syn = cast_syn_expr(r_syn, nl);
5186                    }
5187                }
5188            }
5189            r_syn
5190        };
5191
5192        match op {
5193            AssignOp::Assign => {
5194                let r = normalize_parens(&expr_to_string(&r_syn));
5195                format!("{}{} = {};", indent, l, r)
5196            }
5197            AssignOp::AddAssign | AssignOp::SubAssign => {
5198                if self.is_pointer_expr_unified(lhs, info)
5199                    || lhs_ut.as_ref().is_some_and(|ut| ut.is_pointer()) {
5200                    let method = if *op == AssignOp::AddAssign { "wrapping_add" } else { "wrapping_sub" };
5201                    let r_usize = cast_syn_expr(r_syn, "usize");
5202                    let r = expr_to_string(&r_usize);
5203                    format!("{}{} = {}.{}({});", indent, l, l, method, r)
5204                } else {
5205                    let r = normalize_parens(&expr_to_string(&r_syn));
5206                    format!("{}{} {} {};", indent, l, assign_op_to_rust(*op), r)
5207                }
5208            }
5209            _ => {
5210                let r = normalize_parens(&expr_to_string(&r_syn));
5211                format!("{}{} {} {};", indent, l, assign_op_to_rust(*op), r)
5212            }
5213        }
5214    }
5215
5216    /// 式を文字列に変換(syn::Expr 経由で生成)
5217    fn build_expr_string(&mut self, expr: &Expr, info: Option<&MacroInferInfo>) -> String {
5218        let syn_expr = self.build_syn_expr(expr, info);
5219        normalize_parens(&crate::syn_codegen::expr_to_string(&syn_expr))
5220    }
5221
5222    /// 文を Rust コードに変換(マクロ用)— 統一ヘルパーに委譲
5223    fn stmt_to_rust(&mut self, stmt: &Stmt, info: &MacroInferInfo) -> String {
5224        match stmt {
5225            Stmt::Expr(Some(expr), _) => {
5226                format!("{};", self.build_expr_string(expr, Some(info)))
5227            }
5228            Stmt::Expr(None, _) => ";".to_string(),
5229            Stmt::Return(Some(expr), _) => self.build_return_stmt(expr, "", Some(info)),
5230            Stmt::Return(None, _) => "return;".to_string(),
5231            _ => self.todo_marker("stmt")
5232        }
5233    }
5234
5235    /// TypeName を Rust 型文字列に変換
5236    fn type_name_to_rust(&mut self, type_name: &crate::ast::TypeName) -> String {
5237        // decl_specs_to_rust でベース型を取得(プリミティブ型も正しく変換)
5238        let base_type = self.decl_specs_to_rust(&type_name.specs);
5239
5240        // 宣言子からポインタ/配列/関数を適用
5241        let mut result = if let Some(ref decl) = type_name.declarator {
5242            self.apply_derived_to_type(&base_type, &decl.derived)
5243        } else {
5244            base_type
5245        };
5246
5247        // C の const 修飾子(例: const char*)を Rust の *const に反映
5248        // 最も内側のポインタを *const にする
5249        if type_name.specs.qualifiers.is_const {
5250            if let Some(pos) = result.rfind("*mut ") {
5251                result.replace_range(pos..pos + 5, "*const ");
5252            }
5253        }
5254
5255        result
5256    }
5257
5258    /// DeclSpecs を Rust 型文字列に変換
5259    fn decl_specs_to_rust(&mut self, specs: &DeclSpecs) -> String {
5260        // typedef 名を優先
5261        for spec in &specs.type_specs {
5262            if let TypeSpec::TypedefName(name) = spec {
5263                // 型パラメータなら generic 名に置換
5264                if let Some(generic_name) = self.current_type_param_map.get(name) {
5265                    return generic_name.clone();
5266                }
5267                let name_str = self.interner.get(*name).to_string();
5268                // 未定義型名の検出
5269                if !self.known_symbols.contains(&name_str) {
5270                    self.codegen_errors.push(format!("undefined type: {}", name_str));
5271                }
5272                return name_str;
5273            }
5274        }
5275
5276        // 基本型をチェック
5277        let mut is_void = false;
5278        let mut is_char = false;
5279        let mut is_int = false;
5280        let mut is_short = false;
5281        let mut is_long = 0usize;
5282        let mut is_unsigned = false;
5283        let mut is_float = false;
5284        let mut is_double = false;
5285
5286        for spec in &specs.type_specs {
5287            match spec {
5288                TypeSpec::Void => is_void = true,
5289                TypeSpec::Char => is_char = true,
5290                TypeSpec::Int => is_int = true,
5291                TypeSpec::Short => is_short = true,
5292                TypeSpec::Long => is_long += 1,
5293                TypeSpec::Unsigned => is_unsigned = true,
5294                TypeSpec::Signed => {}
5295                TypeSpec::Float => is_float = true,
5296                TypeSpec::Double => is_double = true,
5297                TypeSpec::Bool => return "bool".to_string(),
5298                TypeSpec::Struct(spec) => {
5299                    if let Some(n) = spec.name {
5300                        return self.interner.get(n).to_string();
5301                    } else {
5302                        return self.type_marker().to_string();
5303                    }
5304                }
5305                TypeSpec::Union(spec) => {
5306                    if let Some(n) = spec.name {
5307                        return self.interner.get(n).to_string();
5308                    } else {
5309                        return self.type_marker().to_string();
5310                    }
5311                }
5312                TypeSpec::Enum(spec) => {
5313                    if let Some(n) = spec.name {
5314                        return self.interner.get(n).to_string();
5315                    } else {
5316                        return "c_int".to_string();
5317                    }
5318                }
5319                _ => {}
5320            }
5321        }
5322
5323        if is_void {
5324            return "()".to_string();
5325        }
5326
5327        if is_float {
5328            return "c_float".to_string();
5329        }
5330
5331        if is_double {
5332            return if is_long > 0 { "c_longdouble".to_string() } else { "c_double".to_string() };
5333        }
5334
5335        if is_char {
5336            return if is_unsigned { "c_uchar".to_string() } else { "c_char".to_string() };
5337        }
5338
5339        if is_short {
5340            return if is_unsigned { "c_ushort".to_string() } else { "c_short".to_string() };
5341        }
5342
5343        if is_long >= 2 {
5344            return if is_unsigned { "c_ulonglong".to_string() } else { "c_longlong".to_string() };
5345        }
5346
5347        if is_long == 1 {
5348            return if is_unsigned { "c_ulong".to_string() } else { "c_long".to_string() };
5349        }
5350
5351        if is_int || is_unsigned {
5352            return if is_unsigned { "c_uint".to_string() } else { "c_int".to_string() };
5353        }
5354
5355        self.type_marker().to_string()
5356    }
5357
5358    /// 派生型を型に適用(関数ポインタを含む完全な処理)
5359    fn apply_derived_to_type(&mut self, base: &str, derived: &[DerivedDecl]) -> String {
5360        // Function を探す
5361        let fn_idx = derived
5362            .iter()
5363            .position(|d| matches!(d, DerivedDecl::Function(_)));
5364
5365        if let Some(idx) = fn_idx {
5366            if let DerivedDecl::Function(param_list) = &derived[idx] {
5367                // Function の直前が Pointer なら関数ポインタ
5368                let is_fn_pointer =
5369                    idx > 0 && matches!(derived[idx - 1], DerivedDecl::Pointer(_));
5370
5371                // 戻り値型の派生(Function と fn ptr Pointer を除く)
5372                let return_end = if is_fn_pointer { idx - 1 } else { idx };
5373                let return_derived = &derived[..return_end];
5374                let return_type = self.apply_simple_derived(base, return_derived);
5375
5376                // パラメータリストを生成(型のみ、名前なし)
5377                let params: Vec<_> = param_list
5378                    .params
5379                    .iter()
5380                    .map(|p| self.param_type_only(p))
5381                    .collect();
5382                let params_str = params.join(", ");
5383
5384                // 関数型を生成
5385                let fn_type =
5386                    format!("unsafe extern \"C\" fn({}) -> {}", params_str, return_type);
5387
5388                // 関数ポインタの場合は Option でラップ(NULL 許容)
5389                if is_fn_pointer {
5390                    return format!("Option<{}>", fn_type);
5391                }
5392                return fn_type;
5393            }
5394        }
5395
5396        // 通常の型変換(Function を含まない場合)
5397        self.apply_simple_derived(base, derived)
5398    }
5399
5400    /// 単純な派生型の適用(Pointer と Array のみ)
5401    fn apply_simple_derived(&self, base: &str, derived: &[DerivedDecl]) -> String {
5402        self.apply_simple_derived_with_specs_const(base, derived, false)
5403    }
5404
5405    /// 派生型を適用(specs の const 情報を考慮)
5406    fn apply_simple_derived_with_specs_const(&self, base: &str, derived: &[DerivedDecl], specs_is_const: bool) -> String {
5407        let mut result = base.to_string();
5408        let mut is_first_pointer = true;
5409        for d in derived.iter().rev() {
5410            match d {
5411                DerivedDecl::Pointer(quals) => {
5412                    // void ポインタの場合は c_void を使用
5413                    if result == "()" {
5414                        result = "c_void".to_string();
5415                    }
5416                    // C の "const T *p": specs.is_const が pointee const を表す
5417                    // C の "T * const p": quals.is_const はポインタ自体の const (Rust では *mut)
5418                    // ただし "const T * const p" は両方 const → *const
5419                    let pointee_const = if is_first_pointer {
5420                        specs_is_const
5421                    } else {
5422                        quals.is_const
5423                    };
5424                    if pointee_const {
5425                        result = format!("*const {}", result);
5426                    } else {
5427                        result = format!("*mut {}", result);
5428                    }
5429                    is_first_pointer = false;
5430                }
5431                DerivedDecl::Array(arr) => {
5432                    // void 配列の場合は c_void を使用
5433                    if result == "()" {
5434                        result = "c_void".to_string();
5435                    }
5436                    if let Some(ref size_expr) = arr.size {
5437                        // 定数サイズ配列
5438                        if let ExprKind::IntLit(n) = &size_expr.kind {
5439                            result = format!("[{}; {}]", result, n);
5440                        } else {
5441                            result = format!("*mut {}", result);
5442                        }
5443                    } else {
5444                        result = format!("*mut {}", result);
5445                    }
5446                }
5447                DerivedDecl::Function(_) => {
5448                    // この関数では Function は処理しない(apply_derived_to_type で処理)
5449                }
5450            }
5451        }
5452        result
5453    }
5454
5455    /// ParamDecl から型のみを取得(名前なし)
5456    fn param_type_only(&mut self, param: &ParamDecl) -> String {
5457        let ty = self.decl_specs_to_rust(&param.specs);
5458        if let Some(ref declarator) = param.declarator {
5459            // specs の const 修飾子 (`const U8 *`) をポインタ const として
5460            // 反映する。apply_derived_to_type は常に specs_is_const=false で
5461            // 呼び出すため、ここで補正する。
5462            self.apply_simple_derived_with_specs_const(&ty, &declarator.derived, param.specs.qualifiers.is_const)
5463        } else {
5464            ty
5465        }
5466    }
5467
5468    /// inline 関数を生成(self を消費)
5469    pub fn generate_inline_fn(mut self, name: crate::InternedStr, func_def: &FunctionDef) -> GeneratedCode {
5470        let name_str = self.interner.get(name);
5471
5472        // mutable パラメータ/ローカル変数を検出
5473        let mut_params = {
5474            let mut all_names = HashSet::new();
5475            // パラメータ名を収集
5476            for d in &func_def.declarator.derived {
5477                if let DerivedDecl::Function(param_list) = d {
5478                    for p in &param_list.params {
5479                        if let Some(ref declarator) = p.declarator {
5480                            if let Some(param_name) = declarator.name {
5481                                all_names.insert(param_name);
5482                            }
5483                        }
5484                    }
5485                }
5486            }
5487            // ローカル変数名も収集
5488            for item in &func_def.body.items {
5489                if let BlockItem::Decl(decl) = item {
5490                    for init_decl in &decl.declarators {
5491                        if let Some(var_name) = init_decl.declarator.name {
5492                            all_names.insert(var_name);
5493                        }
5494                    }
5495                }
5496            }
5497            let mut result = HashSet::new();
5498            for item in &func_def.body.items {
5499                if let BlockItem::Stmt(stmt) = item {
5500                    collect_mut_params_from_stmt(stmt, &all_names, &mut result);
5501                }
5502            }
5503            result
5504        };
5505
5506        // mut ローカル変数名を保存(decl_to_rust_let で使用)
5507        self.mut_local_names = mut_params.clone();
5508
5509        // パラメータリストを取得
5510        let params_str = self.build_fn_param_list(&func_def.declarator.derived, &mut_params);
5511
5512        // 戻り値の型を取得(基本型)
5513        let return_type = self.decl_specs_to_rust(&func_def.specs);
5514
5515        // declarator の派生型(ポインタなど)を適用(Function を除く)
5516        // 例: HEK * func(...) の場合、derived = [Pointer, Function]
5517        //     戻り値型は HEK に Pointer を適用して *mut HEK になる
5518        let return_derived: Vec<_> = func_def.declarator.derived.iter()
5519            .filter(|d| !matches!(d, DerivedDecl::Function(_)))
5520            .cloned()
5521            .collect();
5522        let return_type = self.apply_simple_derived_with_specs_const(&return_type, &return_derived, func_def.specs.qualifiers.is_const);
5523        self.current_return_type = Some(UnifiedType::from_rust_str(&return_type));
5524
5525        // パラメータの型情報を収集 + ローカルスコープに登録
5526        for d in &func_def.declarator.derived {
5527            if let DerivedDecl::Function(param_list) = d {
5528                for p in &param_list.params {
5529                    if let Some(ref declarator) = p.declarator {
5530                        if let Some(param_name) = declarator.name {
5531                            let ty = self.param_type_only(p);
5532                            self.current_param_types.insert(param_name, UnifiedType::from_rust_str(&ty));
5533                            self.current_local_names.insert(param_name);
5534                        }
5535                    }
5536                }
5537            }
5538        }
5539
5540        // 本体のローカル変数宣言もスコープに追加(ネストした compound、
5541        // StmtExpr、for ループ初期化、すべての block レベルを再帰走査)
5542        self.collect_local_names_recursive(&func_def.body);
5543
5544        // THX 依存性を判定(非 threaded では常に false)
5545        let is_thx_dependent = self.perl_threaded
5546            && self.is_inline_fn_thx_dependent(&func_def.declarator.derived);
5547        let thx_info = if is_thx_dependent { " [THX]" } else { "" };
5548
5549        // AST ダンプ(デバッグ用)
5550        self.dump_ast_comment_for_body(name_str, &func_def.body);
5551
5552        // ドキュメントコメント
5553        self.writeln(&format!("/// {}{} - inline function", name_str, thx_info));
5554        self.writeln("#[inline]");
5555        self.writeln("#[allow(unsafe_op_in_unsafe_fn)]");
5556
5557        // 関数定義
5558        self.writeln(&format!("pub unsafe fn {}({}) -> {} {{", name_str, params_str, return_type));
5559
5560        // unsafe 操作(関数呼び出し or デリファレンス)を含む場合のみ unsafe ブロックを生成
5561        let needs_unsafe = func_def.function_call_count > 0 || func_def.deref_count > 0;
5562
5563        if needs_unsafe {
5564            self.writeln("    unsafe {");
5565            let body_str = self.compound_stmt_to_string(&func_def.body, "        ");
5566            self.buffer.push_str(&body_str);
5567            self.writeln("    }");
5568        } else {
5569            let body_str = self.compound_stmt_to_string(&func_def.body, "    ");
5570            self.buffer.push_str(&body_str);
5571        }
5572
5573        self.writeln("}");
5574        self.writeln("");
5575
5576        self.into_generated_code()
5577    }
5578
5579    /// DerivedDecl から関数パラメータリストを構築
5580    fn build_fn_param_list(&mut self, derived: &[DerivedDecl], mut_params: &HashSet<InternedStr>) -> String {
5581        for d in derived {
5582            if let DerivedDecl::Function(param_list) = d {
5583                // C の `fn(void)` は「引数なし」の同義。単独の void パラメータは
5584                // Rust の 0 引数に変換する(そうしないと `fn(_: ())` となり呼出側
5585                // が 0 引数と食い違って E0061 を起こす)。
5586                if is_void_only_param_list(&param_list.params) {
5587                    return String::new();
5588                }
5589                let params: Vec<_> = param_list.params.iter()
5590                    .map(|p| self.param_decl_to_rust(p, mut_params))
5591                    .collect();
5592                let mut result = params.join(", ");
5593                if param_list.is_variadic {
5594                    if !result.is_empty() {
5595                        result.push_str(", ");
5596                    }
5597                    result.push_str("...");
5598                }
5599                return result;
5600            }
5601        }
5602        String::new()
5603    }
5604
5605    /// inline 関数が THX 依存かどうかを判定
5606    ///
5607    /// 最初のパラメータが `my_perl` という名前であれば THX 依存とみなす。
5608    fn is_inline_fn_thx_dependent(&self, derived: &[DerivedDecl]) -> bool {
5609        for d in derived {
5610            if let DerivedDecl::Function(param_list) = d {
5611                if let Some(first_param) = param_list.params.first() {
5612                    if let Some(ref declarator) = first_param.declarator {
5613                        if let Some(name) = declarator.name {
5614                            let name_str = self.interner.get(name);
5615                            return name_str == "my_perl";
5616                        }
5617                    }
5618                }
5619                return false;
5620            }
5621        }
5622        false
5623    }
5624
5625    /// ParamDecl を Rust パラメータ宣言に変換
5626    fn param_decl_to_rust(&mut self, param: &ParamDecl, mut_params: &HashSet<InternedStr>) -> String {
5627        let param_name_interned = param.declarator
5628            .as_ref()
5629            .and_then(|d| d.name);
5630        let name = param_name_interned
5631            .map(|n| escape_rust_keyword(self.interner.get(n)))
5632            .unwrap_or_else(|| "_".to_string());
5633
5634        let ty = self.decl_specs_to_rust(&param.specs);
5635
5636        // ポインタ派生型を適用(specs の const を考慮)
5637        let ty = if let Some(ref declarator) = param.declarator {
5638            self.apply_simple_derived_with_specs_const(&ty, &declarator.derived, param.specs.qualifiers.is_const)
5639        } else {
5640            ty
5641        };
5642
5643        // current_param_types に登録(型推論で使用)
5644        if let Some(n) = param_name_interned {
5645            self.current_param_types.insert(n, UnifiedType::from_rust_str(&ty));
5646        }
5647
5648        let mut_prefix = if param_name_interned.is_some_and(|n| mut_params.contains(&n)) {
5649            "mut "
5650        } else {
5651            ""
5652        };
5653
5654        format!("{}{}: {}", mut_prefix, name, ty)
5655    }
5656
5657    /// Declaration を Rust の let 宣言に変換
5658    fn decl_to_rust_let(&mut self, decl: &Declaration, indent: &str) -> String {
5659        let mut result = String::new();
5660
5661        // 基本型を取得
5662        let base_type = self.decl_specs_to_rust(&decl.specs);
5663
5664        // 各宣言子を処理
5665        for init_decl in &decl.declarators {
5666            let name = init_decl.declarator.name
5667                .map(|n| escape_rust_keyword(self.interner.get(n)))
5668                .unwrap_or_else(|| "_".to_string());
5669
5670            // 派生型(ポインタなど)を適用
5671            let ty = self.apply_derived_to_type(&base_type, &init_decl.declarator.derived);
5672
5673            // 初期化子
5674            if let Some(ref init) = init_decl.init {
5675                match init {
5676                    Initializer::Expr(expr) => {
5677                        // 宣言型と式の推論型が異なる整数型なら as キャストを syn レベルで挿入。
5678                        // 文字列ベースの `({} as {})` は normalize_parens に剥がされて
5679                        // `a as u32 & b as u8` の優先順位崩壊を起こすため、syn::Expr で
5680                        // 構築して expr_to_string に括弧の挿入を任せる。
5681                        let mut init_syn = self.build_syn_expr(expr, None);
5682                        if let Some(expr_ut) = self.infer_expr_type_inline(expr) {
5683                            let decl_s = ty.clone();
5684                            let expr_s = expr_ut.to_rust_string();
5685                            let nd = normalize_integer_type(&decl_s);
5686                            let ne = normalize_integer_type(&expr_s);
5687                            if let (Some(d), Some(e)) = (nd, ne) {
5688                                if !integer_types_compatible(d, e) {
5689                                    init_syn = crate::syn_codegen::cast_syn_expr(init_syn, d);
5690                                }
5691                            }
5692                        }
5693                        // ポインタの const/mut 不一致は init 側に明示キャストを挿入する。
5694                        // 旧実装は宣言型を *const に書換えていたが、それだと以降の
5695                        // 代入で *mut 型が期待されるマクロ引数などで破綻する。
5696                        // 例: `let s: *mut U8 = s0;` (s0: *const U8) → `s0 as *mut U8`
5697                        let decl_is_mut_ptr = ty.contains("*mut ") && !ty.contains("*const ");
5698                        let decl_is_const_ptr = ty.contains("*const ") && !ty.contains("*mut ");
5699                        if let Some(expr_ut) = self.infer_expr_type_inline(expr) {
5700                            if expr_ut.is_pointer() {
5701                                if decl_is_mut_ptr && expr_ut.is_const_pointer() {
5702                                    init_syn = crate::syn_codegen::cast_syn_expr(init_syn, &ty);
5703                                } else if decl_is_const_ptr && !expr_ut.is_const_pointer() {
5704                                    init_syn = crate::syn_codegen::cast_syn_expr(init_syn, &ty);
5705                                }
5706                            }
5707                        }
5708                        let init_expr = normalize_parens(&crate::syn_codegen::expr_to_string(&init_syn));
5709                        // null リテラルの場合は型推論に任せて std::ptr::null_mut()
5710                        let init_expr = if is_null_literal(expr) && ty.contains("*mut") {
5711                            "std::ptr::null_mut()".to_string()
5712                        } else if is_null_literal(expr) && ty.contains("*const") {
5713                            "std::ptr::null()".to_string()
5714                        } else {
5715                            init_expr
5716                        };
5717                        let mut_kw = if init_decl.declarator.name.is_some_and(|n| self.mut_local_names.contains(&n)) { "mut " } else { "" };
5718                        result.push_str(&format!("{}let {}{}: {} = {};\n", indent, mut_kw, name, ty, strip_outer_parens(&init_expr)));
5719                    }
5720                    Initializer::List(_) => {
5721                        // 初期化リストは複雑なので TODO
5722                        result.push_str(&format!("{}let {}: {} = /* init list */;\n", indent, name, ty));
5723                    }
5724                }
5725            } else {
5726                // 初期化子なし(未初期化変数 - Rust では unsafe かデフォルト値が必要)
5727                let mut_kw = if init_decl.declarator.name.is_some_and(|n| self.mut_local_names.contains(&n)) { "mut " } else { "" };
5728                result.push_str(&format!("{}let {}{}: {}; // uninitialized\n", indent, mut_kw, name, ty));
5729            }
5730        }
5731
5732        result
5733    }
5734
5735    /// 複合文を文字列として生成
5736    fn compound_stmt_to_string(&mut self, stmt: &CompoundStmt, indent: &str) -> String {
5737        let mut result = String::new();
5738        for item in &stmt.items {
5739            match item {
5740                BlockItem::Decl(decl) => {
5741                    self.collect_decl_types(decl);
5742                    result.push_str(&self.decl_to_rust_let(decl, indent));
5743                }
5744                BlockItem::Stmt(s) => {
5745                    let rust_stmt = self.stmt_to_rust_inline(s, indent);
5746                    result.push_str(&rust_stmt);
5747                    result.push('\n');
5748                }
5749            }
5750        }
5751        result
5752    }
5753
5754    /// 文を Rust コードに変換(インライン関数用)
5755    fn stmt_to_rust_inline(&mut self, stmt: &Stmt, indent: &str) -> String {
5756        match stmt {
5757            Stmt::Expr(Some(expr), _) => {
5758                // 代入式は値を返さない形式で出力(統一ヘルパー使用)
5759                if let ExprKind::Assign { op, lhs, rhs } = &expr.kind {
5760                    self.build_assign_stmt(op, lhs, rhs, indent, None)
5761                } else {
5762                    format!("{}{};", indent, self.build_expr_string(expr, None))
5763                }
5764            }
5765            Stmt::Expr(None, _) => String::new(),
5766            Stmt::Return(Some(expr), _) => self.build_return_stmt(expr, indent, None),
5767            Stmt::Return(None, _) => format!("{}return;", indent),
5768            Stmt::If { cond, then_stmt, else_stmt, .. } => {
5769                let cond_str = self.build_expr_string(cond, None);
5770                // 条件が既に bool なら != 0 を追加しない
5771                let cond_bool = self.wrap_as_bool_condition_inline(cond, &cond_str);
5772                let mut result = format!("{}if {} {{\n", indent, normalize_parens(&cond_bool));
5773                let nested_indent = format!("{}    ", indent);
5774                result.push_str(&self.stmt_to_rust_inline(then_stmt, &nested_indent));
5775                result.push_str("\n");
5776                result.push_str(&format!("{}}}", indent));
5777                if let Some(else_stmt) = else_stmt {
5778                    result.push_str(" else {\n");
5779                    result.push_str(&self.stmt_to_rust_inline(else_stmt, &nested_indent));
5780                    result.push_str("\n");
5781                    result.push_str(&format!("{}}}", indent));
5782                }
5783                result
5784            }
5785            Stmt::Compound(compound) => {
5786                let mut result = format!("{}{{\n", indent);
5787                for item in &compound.items {
5788                    match item {
5789                        BlockItem::Stmt(s) => {
5790                            let nested_indent = format!("{}    ", indent);
5791                            result.push_str(&self.stmt_to_rust_inline(s, &nested_indent));
5792                            result.push_str("\n");
5793                        }
5794                        BlockItem::Decl(decl) => {
5795                            self.collect_decl_types(decl);
5796                            let nested_indent = format!("{}    ", indent);
5797                            result.push_str(&self.decl_to_rust_let(decl, &nested_indent));
5798                        }
5799                    }
5800                }
5801                result.push_str(&format!("{}}}", indent));
5802                result
5803            }
5804            Stmt::While { cond, body, .. } => {
5805                let cond_str = self.build_expr_string(cond, None);
5806                // 条件が既に bool なら != 0 を追加しない
5807                let cond_bool = self.wrap_as_bool_condition_inline(cond, &cond_str);
5808                let mut result = format!("{}while {} {{\n", indent, cond_bool);
5809                let nested_indent = format!("{}    ", indent);
5810                result.push_str(&self.stmt_to_rust_inline(body, &nested_indent));
5811                result.push_str("\n");
5812                result.push_str(&format!("{}}}", indent));
5813                result
5814            }
5815            Stmt::For { init, cond, step, body, .. } => {
5816                let mut result = format!("{}{{\n", indent);
5817                let nested_indent = format!("{}    ", indent);
5818
5819                // 初期化部分
5820                if let Some(for_init) = init {
5821                    match for_init {
5822                        ForInit::Expr(expr) => {
5823                            result.push_str(&format!("{}{};\n", nested_indent, self.build_expr_string(expr, None)));
5824                        }
5825                        ForInit::Decl(decl) => {
5826                            self.collect_decl_types(decl);
5827                            result.push_str(&self.decl_to_rust_let(decl, &nested_indent));
5828                        }
5829                    }
5830                }
5831
5832                // ループ部分
5833                if let Some(cond_expr) = cond {
5834                    let cond_str = self.build_expr_string(cond_expr, None);
5835                    // 条件が既に bool なら != 0 を追加しない
5836                    let cond_bool = self.wrap_as_bool_condition_inline(cond_expr, &cond_str);
5837                    result.push_str(&format!("{}while {} {{\n", nested_indent, cond_bool));
5838                } else {
5839                    result.push_str(&format!("{}loop {{\n", nested_indent));
5840                }
5841
5842                let body_indent = format!("{}    ", nested_indent);
5843
5844                // ループ本体
5845                result.push_str(&self.stmt_to_rust_inline(body, &body_indent));
5846                result.push_str("\n");
5847
5848                // ステップ部分
5849                if let Some(step_expr) = step {
5850                    result.push_str(&format!("{}{};\n", body_indent, self.build_expr_string(step_expr, None)));
5851                }
5852
5853                result.push_str(&format!("{}}}\n", nested_indent));
5854                result.push_str(&format!("{}}}", indent));
5855                result
5856            }
5857            Stmt::DoWhile { body, cond, .. } => {
5858                // do { ... } while (0) パターンは一度だけ実行される loop として出力
5859                // これにより内部の break; が正しく動作する
5860                if is_zero_constant(cond) {
5861                    // 内部 body に `break;` が含まれなければ単なる block で十分。
5862                    // STMT_START/STMT_END 由来なら break なしのケースがほとんど。
5863                    // その方が `loop {...break;}` の `()`-型による tail 型不一致
5864                    // (fn が usize 等を返す場合の E0308) を避けられる。
5865                    if !stmt_contains_top_level_break(body) {
5866                        let mut result = format!("{}{{\n", indent);
5867                        let nested_indent = format!("{}    ", indent);
5868                        result.push_str(&self.stmt_to_rust_inline(body, &nested_indent));
5869                        result.push_str("\n");
5870                        result.push_str(&format!("{}}}", indent));
5871                        return result;
5872                    }
5873                    let mut result = format!("{}loop {{\n", indent);
5874                    let nested_indent = format!("{}    ", indent);
5875                    result.push_str(&self.stmt_to_rust_inline(body, &nested_indent));
5876                    result.push_str("\n");
5877                    result.push_str(&format!("{}    break;\n", indent));
5878                    result.push_str(&format!("{}}}", indent));
5879                    return result;
5880                }
5881
5882                // 一般的な do-while 文: loop { body; if !cond { break; } }
5883                let mut result = format!("{}loop {{\n", indent);
5884                let nested_indent = format!("{}    ", indent);
5885                result.push_str(&self.stmt_to_rust_inline(body, &nested_indent));
5886                result.push_str("\n");
5887                let cond_str = self.build_expr_string(cond, None);
5888                // bool 式なら !(cond)、そうでなければ cond == 0
5889                // `!{}` 直付けだと `!a < b` のように優先順位で Lt が bind され、
5890                // `cannot apply ! to pointer` 等の誤生成になる。
5891                let break_cond = if is_boolean_expr(cond) {
5892                    normalize_parens(&format!("!({})", cond_str))
5893                } else {
5894                    format!("{} == 0", cond_str)
5895                };
5896                result.push_str(&format!("{}    if {} {{ break; }}\n", indent, break_cond));
5897                result.push_str(&format!("{}}}", indent));
5898                result
5899            }
5900            Stmt::Switch { expr, body, .. } => {
5901                let expr_str = self.build_expr_string(expr, None);
5902                let mut result = format!("{}match {} {{\n", indent, expr_str);
5903                let nested_indent = format!("{}    ", indent);
5904
5905                // body から Case/Default を収集
5906                self.collect_switch_cases(body, &nested_indent, &mut result);
5907
5908                result.push_str(&format!("{}}}", indent));
5909                result
5910            }
5911            Stmt::Case { expr: case_expr, stmt: case_stmt, .. } => {
5912                // Switch 外で Case が出現した場合(通常は Switch 内で処理される)
5913                let case_val = self.build_expr_string(case_expr, None);
5914                let mut result = format!("{}{} => {{\n", indent, case_val);
5915                let body_indent = format!("{}    ", indent);
5916                result.push_str(&self.stmt_to_rust_inline(case_stmt, &body_indent));
5917                result.push_str("\n");
5918                result.push_str(&format!("{}}}", indent));
5919                result
5920            }
5921            Stmt::Default { stmt: default_stmt, .. } => {
5922                let mut result = format!("{}_ => {{\n", indent);
5923                let body_indent = format!("{}    ", indent);
5924                result.push_str(&self.stmt_to_rust_inline(default_stmt, &body_indent));
5925                result.push_str("\n");
5926                result.push_str(&format!("{}}}", indent));
5927                result
5928            }
5929            Stmt::Goto(label, _) => {
5930                let label_str = self.interner.get(*label);
5931                format!("{}break '{}; // goto", indent, label_str)
5932            }
5933            Stmt::Label { name, stmt: label_stmt, .. } => {
5934                let label_str = self.interner.get(*name);
5935                let mut result = format!("{}'{}: {{\n", indent, label_str);
5936                let nested_indent = format!("{}    ", indent);
5937                result.push_str(&self.stmt_to_rust_inline(label_stmt, &nested_indent));
5938                result.push_str("\n");
5939                result.push_str(&format!("{}}}", indent));
5940                result
5941            }
5942            Stmt::Break(_) => format!("{}break;", indent),
5943            Stmt::Continue(_) => format!("{}continue;", indent),
5944            _ => self.todo_marker(&format!("{:?}", std::mem::discriminant(stmt)))
5945        }
5946    }
5947
5948    /// Switch 文の body から Case/Default を収集して match アームを生成
5949    fn collect_switch_cases(&mut self, stmt: &Stmt, indent: &str, result: &mut String) {
5950        // パス1: case/default とそれに続く文を収集
5951        struct SwitchCase {
5952            patterns: Vec<String>,   // case 式のリスト(複数 case ラベル対応)、空 = default
5953            body_stmts: Vec<String>,
5954            is_default: bool,
5955        }
5956
5957        let mut cases: Vec<SwitchCase> = Vec::new();
5958        let body_indent = format!("{}    ", indent);
5959
5960        // Compound の中身をフラット化して処理
5961        fn collect_items<'a>(stmt: &'a Stmt, items: &mut Vec<&'a BlockItem>) {
5962            if let Stmt::Compound(compound) = stmt {
5963                for item in &compound.items {
5964                    items.push(item);
5965                }
5966            }
5967        }
5968
5969        // ネストされた case/default を展開して patterns と最終的な stmt を取得
5970        fn flatten_case_chain<'a>(stmt: &'a Stmt, patterns: &mut Vec<&'a Expr>) -> (&'a Stmt, bool) {
5971            match stmt {
5972                Stmt::Case { expr, stmt: inner_stmt, .. } => {
5973                    patterns.push(expr);
5974                    flatten_case_chain(inner_stmt, patterns)
5975                }
5976                Stmt::Default { stmt: inner_stmt, .. } => {
5977                    // default に到達
5978                    (inner_stmt, true)
5979                }
5980                other => (other, false)
5981            }
5982        }
5983
5984        let mut items: Vec<&BlockItem> = Vec::new();
5985        collect_items(stmt, &mut items);
5986
5987        for item in items {
5988            match item {
5989                BlockItem::Stmt(s) => {
5990                    match s {
5991                        Stmt::Case { expr: case_expr, stmt: case_stmt, .. } => {
5992                            // ネストされた case をフラット化
5993                            let mut patterns: Vec<&Expr> = vec![case_expr];
5994                            let (final_stmt, has_default) = flatten_case_chain(case_stmt, &mut patterns);
5995
5996                            // パターンは enum バリアントをフルパスで出力
5997                            let pattern_strs: Vec<String> = patterns.iter()
5998                                .map(|e| self.expr_to_rust_pattern(e))
5999                                .collect();
6000
6001                            // final_stmt が Break の場合はスキップ(Rust の match は break 不要)
6002                            let body_stmts = if matches!(final_stmt, Stmt::Break(_)) {
6003                                vec![]
6004                            } else {
6005                                vec![self.stmt_to_rust_inline(final_stmt, &body_indent)]
6006                            };
6007                            cases.push(SwitchCase {
6008                                patterns: pattern_strs,
6009                                body_stmts,
6010                                is_default: has_default,
6011                            });
6012                        }
6013                        Stmt::Default { stmt: default_stmt, .. } => {
6014                            // ネストされた case をフラット化
6015                            let mut patterns: Vec<&Expr> = Vec::new();
6016                            let (final_stmt, _) = flatten_case_chain(default_stmt, &mut patterns);
6017
6018                            // パターンは enum バリアントをフルパスで出力
6019                            let pattern_strs: Vec<String> = patterns.iter()
6020                                .map(|e| self.expr_to_rust_pattern(e))
6021                                .collect();
6022
6023                            // final_stmt が Break の場合はスキップ(Rust の match は break 不要)
6024                            let body_stmts = if matches!(final_stmt, Stmt::Break(_)) {
6025                                vec![]
6026                            } else {
6027                                vec![self.stmt_to_rust_inline(final_stmt, &body_indent)]
6028                            };
6029                            cases.push(SwitchCase {
6030                                patterns: pattern_strs,
6031                                body_stmts,
6032                                is_default: true,
6033                            });
6034                        }
6035                        Stmt::Break(_) => {
6036                            // Rust の match はフォールスルーしないので break は不要
6037                            // スキップする
6038                        }
6039                        other => {
6040                            // 直前の case に追加
6041                            if let Some(last) = cases.last_mut() {
6042                                last.body_stmts.push(self.stmt_to_rust_inline(other, &body_indent));
6043                            }
6044                            // case がまだない場合は無視
6045                        }
6046                    }
6047                }
6048                BlockItem::Decl(decl) => {
6049                    self.collect_decl_types(decl);
6050                    // 宣言は直前の case に追加
6051                    if let Some(last) = cases.last_mut() {
6052                        last.body_stmts.push(self.decl_to_rust_let(decl, &body_indent));
6053                    }
6054                }
6055            }
6056        }
6057
6058        // パス2: 収集した cases から match アームを生成
6059        let has_default = cases.iter().any(|c| c.is_default);
6060        for case in &cases {
6061            let pattern = if case.is_default {
6062                if case.patterns.is_empty() {
6063                    "_".to_string()
6064                } else {
6065                    // case A: case B: default: ... のパターン
6066                    format!("{} | _", case.patterns.join(" | "))
6067                }
6068            } else {
6069                case.patterns.join(" | ")
6070            };
6071
6072            result.push_str(&format!("{}{} => {{\n", indent, pattern));
6073            for stmt in &case.body_stmts {
6074                result.push_str(stmt);
6075                result.push_str("\n");
6076            }
6077            result.push_str(&format!("{}}}\n", indent));
6078        }
6079        // C の switch は default が無ければ該当しない値を素通しする。
6080        // Rust match は網羅性が必要なため、default 無しのケースで
6081        // `_ => {}` を自動挿入する。
6082        if !has_default {
6083            result.push_str(&format!("{}_ => {{}}\n", indent));
6084        }
6085    }
6086
6087    /// offsetof のフィールドパス式をドット区切り文字列に変換
6088    /// Ident("xnv_u") → "xnv_u"
6089    /// Member(Ident("xnv_u"), "xnv_nv") → "xnv_u.xnv_nv"
6090    fn expr_to_field_path(&self, expr: &Expr) -> Option<String> {
6091        match &expr.kind {
6092            ExprKind::Ident(name) => {
6093                Some(self.interner.get(*name).to_string())
6094            }
6095            ExprKind::Member { expr: base, member } => {
6096                let base_path = self.expr_to_field_path(base)?;
6097                let member_name = self.interner.get(*member);
6098                Some(format!("{}.{}", base_path, member_name))
6099            }
6100            _ => None,
6101        }
6102    }
6103
6104
6105    /// match パターン用の式を Rust に変換
6106    ///
6107    /// 通常の式変換と異なり、enum バリアントをフルパスで出力する。
6108    /// Rust の match パターンでは、単純な識別子は変数束縛として扱われるため、
6109    /// enum バリアントは `crate::EnumName::VariantName` 形式で出力する必要がある。
6110    fn expr_to_rust_pattern(&mut self, expr: &Expr) -> String {
6111        match &expr.kind {
6112            ExprKind::Ident(name) => {
6113                // enum バリアントかチェック
6114                if let Some(enum_name) = self.enum_dict.get_enum_for_variant(*name) {
6115                    let enum_str = self.interner.get(enum_name);
6116                    let variant_str = self.interner.get(*name);
6117                    format!("crate::{}::{}", enum_str, variant_str)
6118                } else {
6119                    escape_rust_keyword(self.interner.get(*name))
6120                }
6121            }
6122            // 他の式は通常の変換
6123            _ => self.build_expr_string(expr, None)
6124        }
6125    }
6126}
6127
6128impl<'a, W: Write> CodegenDriver<'a, W> {
6129    /// 新しいコード生成ドライバを作成
6130    pub fn new(
6131        writer: W,
6132        interner: &'a StringInterner,
6133        enum_dict: &'a EnumDict,
6134        macro_ctx: &'a MacroInferContext,
6135        bindings_info: BindingsInfo,
6136        config: CodegenConfig,
6137    ) -> Self {
6138        Self {
6139            writer,
6140            interner,
6141            enum_dict,
6142            macro_ctx,
6143            bindings_info,
6144            config,
6145            stats: CodegenStats::default(),
6146            report: CodegenReport::default(),
6147            used_libc_fns: HashSet::new(),
6148            successfully_generated_inlines: HashSet::new(),
6149            generatable_macros: HashSet::new(),
6150            const_pointer_params: HashMap::new(),
6151            bool_return_macros: HashSet::new(),
6152            // デフォルトは threaded(後方互換)。`generate()` で
6153            // result.perl_build_mode から書き換える。
6154            perl_threaded: true,
6155        }
6156    }
6157
6158    /// 対象 perl が threaded かを設定
6159    pub fn with_perl_threaded(mut self, threaded: bool) -> Self {
6160        self.perl_threaded = threaded;
6161        self
6162    }
6163
6164    /// 統計情報を取得
6165    pub fn stats(&self) -> &CodegenStats {
6166        &self.stats
6167    }
6168
6169    /// 関数別の生成結果を取得 (generate() 完了後に有効)
6170    pub fn report(&self) -> &CodegenReport {
6171        &self.report
6172    }
6173
6174    /// 全体を生成
6175    // デバッグ用: ビルド時のタイムスタンプを埋め込む場合はコメントを外す
6176    // const BUILD_TIMESTAMP: &'static str = "2025-01-24T17:50:00+09:00";
6177
6178    pub fn generate(&mut self, result: &InferResult) -> io::Result<()> {
6179        // 対象 perl の threaded フラグを反映(is_thx_dependent 経路の防御的ガード)
6180        self.perl_threaded = result.perl_build_mode.is_threaded();
6181
6182        // 自動生成 struct/typedef を先に決定(known_symbols 構築前)
6183        // 実際に出力される名前のみ known_symbols に登録するため、emit を先行実施。
6184        let missing_structs = crate::struct_emitter::emit_missing_structs(
6185            &result.fields_dict,
6186            result.rust_decl_dict.as_ref(),
6187            self.interner,
6188        );
6189        let static_arrays = crate::static_array_emitter::emit_static_arrays(
6190            &result.global_const_dict,
6191            &result.fields_dict,
6192            result.rust_decl_dict.as_ref(),
6193            self.interner,
6194        );
6195        // 自動生成した static 配列名を bindings_info.static_arrays / static_types に登録。
6196        // これにより codegen が `.as_ptr()` 減衰を掛けるべき配列として認識し、
6197        // 要素型 T も `(&raw const NAME) as *const T` で正しく出せる。
6198        for n in &static_arrays.emitted_names {
6199            self.bindings_info.static_arrays.insert(n.clone());
6200        }
6201        for (n, t) in &static_arrays.emitted_types {
6202            self.bindings_info.static_types.insert(n.clone(), t.clone());
6203        }
6204
6205        // 既知シンボル集合を構築(未解決シンボル検出用)
6206        let mut known_symbols = KnownSymbols::new(result, self.interner);
6207        for n in &missing_structs.emitted_struct_names {
6208            known_symbols.insert(n.clone());
6209        }
6210        for n in &missing_structs.emitted_typedef_names {
6211            known_symbols.insert(n.clone());
6212        }
6213
6214        // 自動生成 struct の bit-field アクセサを bindings_info にマージ。
6215        // これにより `is_bitfield_method` がそれらの getter 名を認識し、
6216        // `.name` → `.name()` / `.name = val` → `.set_name(val)` の書換が効く。
6217        for (struct_name, methods) in &missing_structs.bitfield_methods {
6218            self.bindings_info
6219                .bitfield_methods
6220                .entry(struct_name.clone())
6221                .or_default()
6222                .extend(methods.iter().cloned());
6223        }
6224        // global_const_dict 由来の static 配列は既に KnownSymbols::new 内で
6225        // 登録済みなので追加不要
6226
6227        // ヘッダーコメント
6228        writeln!(self.writer, "// Auto-generated Rust bindings")?;
6229        // デバッグ用: タイムスタンプを出力する場合はコメントを外す
6230        // writeln!(self.writer, "// Generated by libperl-macrogen (build: {})", Self::BUILD_TIMESTAMP)?;
6231        writeln!(self.writer, "// Generated by libperl-macrogen")?;
6232        writeln!(self.writer)?;
6233
6234        // use 文を出力
6235        self.generate_use_statements()?;
6236
6237        // target enum のバリアントを import
6238        self.generate_enum_imports(result)?;
6239
6240        // 自動生成 struct/union 定義を出力
6241        if !missing_structs.source.is_empty() {
6242            self.writer.write_all(missing_structs.source.as_bytes())?;
6243        }
6244
6245        // 自動生成 static const 配列を出力(事前算出済み)
6246        if !static_arrays.source.is_empty() {
6247            self.writer.write_all(static_arrays.source.as_bytes())?;
6248        }
6249
6250        // マクロの生成可能性を事前計算(inline→macro カスケード検出用)
6251        self.precompute_macro_generability(result, &known_symbols);
6252
6253        // Phase 2 の解析結果を収集(inline/macro 両方で使用)
6254        for (&name, info) in &result.infer_ctx.macros {
6255            if info.is_bool_return {
6256                self.bool_return_macros.insert(name);
6257            }
6258        }
6259
6260        // inline 関数セクション
6261        if self.config.emit_inline_fns {
6262            self.generate_inline_fns(result, &known_symbols)?;
6263        }
6264
6265        // マクロセクション
6266        if self.config.emit_macros {
6267            self.generate_macros(result, &known_symbols)?;
6268        }
6269
6270        // 使用された libc 関数の use 文を出力(rustfmt が先頭に移動する)
6271        if !self.used_libc_fns.is_empty() {
6272            let mut fns: Vec<_> = self.used_libc_fns.iter().cloned().collect();
6273            fns.sort();
6274            writeln!(self.writer, "use libc::{{{}}};", fns.join(", "))?;
6275        }
6276
6277        Ok(())
6278    }
6279
6280    /// use 文を生成
6281    fn generate_use_statements(&mut self) -> io::Result<()> {
6282        let statements = if self.config.use_statements.is_empty() {
6283            CodegenConfig::default_use_statements()
6284        } else {
6285            self.config.use_statements.clone()
6286        };
6287
6288        if !statements.is_empty() {
6289            for stmt in &statements {
6290                writeln!(self.writer, "{};", stmt)?;
6291            }
6292            writeln!(self.writer)?;
6293        }
6294
6295        Ok(())
6296    }
6297
6298    /// target enum のバリアントを import
6299    ///
6300    /// bindings.rs に存在する enum のみ import する
6301    fn generate_enum_imports(&mut self, result: &InferResult) -> io::Result<()> {
6302        let enum_names = result.enum_dict.target_enum_names(self.interner);
6303        let bindings_enums = result.rust_decl_dict.as_ref().map(|d| &d.enums);
6304
6305        // bindings.rs に存在する enum のみフィルタリング
6306        let filtered_names: Vec<_> = enum_names
6307            .into_iter()
6308            .filter(|name| {
6309                bindings_enums.map_or(true, |enums| enums.contains(*name))
6310            })
6311            .collect();
6312
6313        if !filtered_names.is_empty() {
6314            writeln!(self.writer, "// Enum variant imports")?;
6315            for name in filtered_names {
6316                writeln!(self.writer, "#[allow(unused_imports)]")?;
6317                writeln!(self.writer, "use crate::{}::*;", name)?;
6318            }
6319            writeln!(self.writer)?;
6320        }
6321
6322        Ok(())
6323    }
6324
6325    /// マクロの生成可能性を事前計算
6326    ///
6327    /// inline 関数生成前に呼び出し、マクロ→マクロのカスケード検査をシミュレートして
6328    /// 正常に生成可能なマクロの集合を構築する。
6329    /// inline→macro のカスケード検出に使用する。
6330    fn precompute_macro_generability(&mut self, result: &InferResult, known_symbols: &KnownSymbols) {
6331        // 対象マクロを収集
6332        let macros: Vec<_> = result.infer_ctx.macros.iter()
6333            .filter(|(_, info)| self.should_include_macro(info))
6334            .collect();
6335        let included_set: HashSet<InternedStr> = macros.iter().map(|(n, _)| **n).collect();
6336
6337        // 依存順にソート(葉マクロ先頭)
6338        let sorted_names = self.topological_sort_macros(&macros);
6339
6340        for name in sorted_names {
6341            let info = result.infer_ctx.macros.get(&name).unwrap();
6342
6343            // apidoc_suppressed なマクロは generatable_macros に入れない
6344            // (Phase 3 の早期 SUPPRESSED 分岐で抑止される。inline→macro の
6345            //   cascade 検査が `generatable_macros` を参照するので、ここで
6346            //   除外しないと skip_codegen 対象を呼ぶ inline が誤って success
6347            //   扱いになる抜け穴ができる)
6348            if info.apidoc_suppressed {
6349                continue;
6350            }
6351
6352            // カスケード検査: called_functions が生成不可なマクロを含むか
6353            // 被呼び出し先の判定は is_unavailable_for_codegen() を使う
6354            // (= apidoc_suppressed 由来の不可も Phase 2 propagation で
6355            //   calls_unavailable に流れているはずだが、防御的に OR を取る)
6356            let has_cascade_failure = info.called_functions.iter().any(|called| {
6357                if included_set.contains(called) {
6358                    return result.infer_ctx.macros.get(called)
6359                        .map(|u| u.is_parseable() && !u.is_unavailable_for_codegen())
6360                        .unwrap_or(false)
6361                        && !self.generatable_macros.contains(called);
6362                }
6363                false
6364            });
6365            if has_cascade_failure {
6366                continue;
6367            }
6368
6369            // get_macro_status + trial codegen による判定
6370            let status = self.get_macro_status(info);
6371            if status == GenerateStatus::Success {
6372                // 実際に codegen を試行して完全性を確認
6373                let codegen = RustCodegen::new(
6374                    self.interner, self.enum_dict, self.macro_ctx,
6375                    self.bindings_info.clone(), &known_symbols,
6376                    result.rust_decl_dict.as_ref(), Some(&result.inline_fn_dict),
6377                ).with_perl_threaded(self.perl_threaded);
6378                let generated = codegen.generate_macro(info);
6379                if generated.is_complete() && !generated.has_unresolved_names() {
6380                    self.generatable_macros.insert(name);
6381                }
6382            }
6383        }
6384    }
6385
6386    /// inline 関数セクションを生成
6387    ///
6388    /// 2パス方式:
6389    /// - Pass 1: 各 inline 関数を生成し、結果を蓄積
6390    /// - Pass 2: カスケード検査 — 生成成功した関数が失敗した inline 関数や
6391    ///   マクロを呼び出している場合、CASCADE_UNAVAILABLE に降格
6392    pub fn generate_inline_fns(&mut self, result: &InferResult, known_symbols: &KnownSymbols) -> io::Result<()> {
6393        writeln!(self.writer, "// =============================================================================")?;
6394        writeln!(self.writer, "// Inline Functions")?;
6395        writeln!(self.writer, "// =============================================================================")?;
6396        writeln!(self.writer)?;
6397
6398        // 名前順にソート
6399        let mut fns: Vec<_> = result.inline_fn_dict.iter()
6400            .filter(|(_, func_def)| func_def.is_target)
6401            .collect();
6402        fns.sort_by_key(|(name, _)| self.interner.get(**name));
6403
6404        // 対象 inline 関数名の集合
6405        let inline_set: HashSet<InternedStr> = fns.iter().map(|(n, _)| **n).collect();
6406
6407        // Pass 1: 各 inline 関数を生成
6408        enum InlineGenResult {
6409            CallsUnavailable,
6410            ContainsGoto,
6411            UnresolvedNames { code: String, unresolved: Vec<String> },
6412            CodegenError { code: String, errors: Vec<String> },
6413            Incomplete { code: String },
6414            Success { code: String, used_libc: HashSet<String> },
6415            Suppressed { reason: String },
6416        }
6417
6418        let mut gen_results: Vec<(InternedStr, InlineGenResult)> = Vec::new();
6419
6420        for (name, func_def) in &fns {
6421            // apidoc skip_codegen 対象(Phase 2 で apidoc_suppressed 済)は
6422            // 早期に Suppressed。reason 文字列は apidoc_patches から取得。
6423            if result.inline_fn_dict.is_apidoc_suppressed(**name) {
6424                let n_str = self.interner.get(**name);
6425                let reason = result.apidoc_patches.skip_reason(n_str)
6426                    .unwrap_or("apidoc skip_codegen")
6427                    .to_string();
6428                gen_results.push((**name,
6429                    InlineGenResult::Suppressed { reason }));
6430                continue;
6431            }
6432
6433            // 事前に unavailable と判定された関数はスキップ
6434            if result.inline_fn_dict.is_calls_unavailable(**name) {
6435                gen_results.push((**name, InlineGenResult::CallsUnavailable));
6436                continue;
6437            }
6438
6439            if block_items_contain_goto(&func_def.body.items) {
6440                gen_results.push((**name, InlineGenResult::ContainsGoto));
6441                continue;
6442            }
6443
6444            let codegen = RustCodegen::new(self.interner, self.enum_dict, self.macro_ctx, self.bindings_info.clone(), known_symbols, result.rust_decl_dict.as_ref(), Some(&result.inline_fn_dict))
6445                .with_perl_threaded(self.perl_threaded)
6446                .with_dump_ast_for(self.config.dump_ast_for.clone())
6447                        .with_dump_types_for(self.config.dump_types_for.clone())
6448                .with_fields_dict(&result.fields_dict)
6449                .with_bool_return(false, self.bool_return_macros.clone());
6450            let generated = codegen.generate_inline_fn(**name, func_def);
6451
6452            if generated.has_unresolved_names() {
6453                gen_results.push((**name, InlineGenResult::UnresolvedNames {
6454                    code: generated.code,
6455                    unresolved: generated.unresolved_names,
6456                }));
6457            } else if !generated.codegen_errors.is_empty() {
6458                gen_results.push((**name, InlineGenResult::CodegenError {
6459                    code: generated.code,
6460                    errors: generated.codegen_errors,
6461                }));
6462            } else if generated.is_complete() {
6463                gen_results.push((**name, InlineGenResult::Success {
6464                    code: generated.code,
6465                    used_libc: generated.used_libc_fns,
6466                }));
6467            } else {
6468                gen_results.push((**name, InlineGenResult::Incomplete {
6469                    code: generated.code,
6470                }));
6471            }
6472        }
6473
6474        // Pass 1.5: successfully_generated_inlines を構築(Success のみ)
6475        for (name, gen_result) in &gen_results {
6476            if matches!(gen_result, InlineGenResult::Success { .. }) {
6477                self.successfully_generated_inlines.insert(*name);
6478            }
6479        }
6480
6481        // Pass 2: カスケード検査 — Success だが失敗した依存先を呼び出す場合は降格
6482        // InlineFnDict の called_functions を使用(ad-hoc 収集不要)
6483        // inline→inline と inline→macro の両方を検査
6484        // 繰り返し伝播(fixpoint)
6485        let mut changed = true;
6486        while changed {
6487            changed = false;
6488            let current_success = self.successfully_generated_inlines.clone();
6489            for (name, _) in &gen_results {
6490                if !current_success.contains(name) {
6491                    continue;
6492                }
6493                if let Some(calls) = result.inline_fn_dict.get_called_functions(*name) {
6494                    let has_unavailable = calls.iter().any(|called| {
6495                        // inline→inline: 対象 inline が生成失敗
6496                        if inline_set.contains(called) && !current_success.contains(called) {
6497                            return true;
6498                        }
6499                        // inline→macro: 対象マクロが生成不可
6500                        if let Some(macro_info) = result.infer_ctx.macros.get(called) {
6501                            if macro_info.is_target && self.should_include_macro(macro_info) {
6502                                if !self.generatable_macros.contains(called) {
6503                                    return true;
6504                                }
6505                            }
6506                        }
6507                        false
6508                    });
6509                    if has_unavailable {
6510                        self.successfully_generated_inlines.remove(name);
6511                        changed = true;
6512                    }
6513                }
6514            }
6515        }
6516
6517        // Pass 3: 出力
6518        for (name, gen_result) in gen_results {
6519            match gen_result {
6520                InlineGenResult::CallsUnavailable => {
6521                    let name_str = self.interner.get(name);
6522                    let calls = result.inline_fn_dict.get_called_functions(name);
6523                    // 原因を分類: 純粋に存在しない関数を呼ぶ (absent) と
6524                    // 推移的に unavailable な依存先を呼ぶ (cascade) を区別する。
6525                    let absent: Vec<String> = calls
6526                        .map(|cs| cs.iter()
6527                            .filter(|c| {
6528                                let fn_name = self.interner.get(**c);
6529                                !self.is_function_available(**c, fn_name, result)
6530                            })
6531                            .map(|c| self.interner.get(*c).to_string())
6532                            .collect())
6533                        .unwrap_or_default();
6534                    let cascade_deps: Vec<String> = calls
6535                        .map(|cs| cs.iter()
6536                            .filter(|c| {
6537                                let is_unavailable_inline = result.inline_fn_dict.get(**c).is_some()
6538                                    && result.inline_fn_dict.is_unavailable_for_codegen(**c);
6539                                let is_unavailable_macro = result.infer_ctx.macros.get(c)
6540                                    .map(|info| info.is_unavailable_for_codegen())
6541                                    .unwrap_or(false);
6542                                is_unavailable_inline || is_unavailable_macro
6543                            })
6544                            .map(|c| self.interner.get(*c).to_string())
6545                            .collect())
6546                        .unwrap_or_default();
6547                    // HashSet 由来の列挙順を決定化 (run ごとのコメント揺れ防止)
6548                    let mut cascade_deps = cascade_deps;
6549                    cascade_deps.sort();
6550                    let mut absent = absent;
6551                    absent.sort();
6552                    if absent.is_empty() {
6553                        writeln!(self.writer,
6554                            "// [CASCADE_UNAVAILABLE] {} - dependency not generated: {}",
6555                            name_str, cascade_deps.join(", "))?;
6556                        self.report.record_skip(name_str, format!(
6557                            "CASCADE_UNAVAILABLE: dependency not generated: {}",
6558                            cascade_deps.join(", ")));
6559                    } else {
6560                        writeln!(self.writer,
6561                            "// [CALLS_UNAVAILABLE] {} - calls unavailable function(s): {}",
6562                            name_str, absent.join(", "))?;
6563                        self.report.record_skip(name_str, format!(
6564                            "CALLS_UNAVAILABLE: calls unavailable function(s): {}",
6565                            absent.join(", ")));
6566                    }
6567                    writeln!(self.writer)?;
6568                    self.stats.inline_fns_cascade_unavailable += 1;
6569                }
6570                InlineGenResult::ContainsGoto => {
6571                    let name_str = self.interner.get(name);
6572                    writeln!(self.writer, "// [CONTAINS_GOTO] {} - excluded (contains goto)", name_str)?;
6573                    writeln!(self.writer)?;
6574                    self.report.record_skip(name_str, "CONTAINS_GOTO: excluded (contains goto)");
6575                    self.stats.inline_fns_contains_goto += 1;
6576                }
6577                InlineGenResult::Suppressed { reason } => {
6578                    let name_str = self.interner.get(name);
6579                    writeln!(self.writer,
6580                        "// [CODEGEN_SUPPRESSED] {} - inline function (apidoc patch)",
6581                        name_str)?;
6582                    writeln!(self.writer, "// Reason: {}", reason)?;
6583                    writeln!(self.writer)?;
6584                    self.report.record_skip(name_str, format!(
6585                        "CODEGEN_SUPPRESSED (apidoc patch): {}", reason));
6586                }
6587                InlineGenResult::UnresolvedNames { code, unresolved } => {
6588                    let name_str = self.interner.get(name);
6589                    let mut unresolved = unresolved.clone();
6590                    unresolved.sort(); // 列挙順の決定化
6591                    writeln!(self.writer, "// [UNRESOLVED_NAMES] {} - inline function", name_str)?;
6592                    writeln!(self.writer, "// Unresolved: {}", unresolved.join(", "))?;
6593                    for line in code.lines() {
6594                        writeln!(self.writer, "// {}", line)?;
6595                    }
6596                    writeln!(self.writer)?;
6597                    self.report.record_skip(name_str, format!(
6598                        "UNRESOLVED_NAMES: {}", unresolved.join(", ")));
6599                    self.stats.inline_fns_unresolved_names += 1;
6600                }
6601                InlineGenResult::CodegenError { code, errors } => {
6602                    let name_str = self.interner.get(name);
6603                    writeln!(self.writer, "// [CODEGEN_ERROR] {} - inline function", name_str)?;
6604                    for err in &errors {
6605                        writeln!(self.writer, "//   {}", err)?;
6606                    }
6607                    for line in code.lines() {
6608                        writeln!(self.writer, "// {}", line)?;
6609                    }
6610                    writeln!(self.writer)?;
6611                    self.report.record_skip(name_str, format!(
6612                        "CODEGEN_ERROR: {}", errors.join("; ")));
6613                }
6614                InlineGenResult::Incomplete { code } => {
6615                    let name_str = self.interner.get(name);
6616                    writeln!(self.writer, "// [CODEGEN_INCOMPLETE] {} - inline function", name_str)?;
6617                    for line in code.lines() {
6618                        writeln!(self.writer, "// {}", line)?;
6619                    }
6620                    writeln!(self.writer)?;
6621                    self.report.record_skip(name_str, "CODEGEN_INCOMPLETE: type inference incomplete");
6622                    self.stats.inline_fns_type_incomplete += 1;
6623                }
6624                InlineGenResult::Success { code, used_libc } => {
6625                    if self.successfully_generated_inlines.contains(&name) {
6626                        // 正常出力
6627                        write!(self.writer, "{}", code)?;
6628                        self.used_libc_fns.extend(used_libc.iter().cloned());
6629                        self.report.record_emit(self.interner.get(name));
6630                        self.stats.inline_fns_success += 1;
6631                    } else {
6632                        // カスケード降格: 呼び出し先の inline 関数が codegen 時に失敗
6633                        let name_str = self.interner.get(name);
6634                        let mut unavailable: Vec<String> = result.inline_fn_dict.get_called_functions(name)
6635                            .map(|calls| calls.iter()
6636                                .filter(|c| inline_set.contains(c) && !self.successfully_generated_inlines.contains(c))
6637                                .map(|c| self.interner.get(*c).to_string())
6638                                .collect())
6639                            .unwrap_or_default();
6640                        unavailable.sort(); // 列挙順の決定化
6641                        writeln!(self.writer, "// [CASCADE_UNAVAILABLE] {} - dependency not generated: {}",
6642                            name_str, unavailable.join(", "))?;
6643                        for line in code.lines() {
6644                            writeln!(self.writer, "// {}", line)?;
6645                        }
6646                        writeln!(self.writer)?;
6647                        self.report.record_skip(name_str, format!(
6648                            "CASCADE_UNAVAILABLE: dependency not generated: {}",
6649                            unavailable.join(", ")));
6650                        self.stats.inline_fns_cascade_unavailable += 1;
6651                    }
6652                }
6653            }
6654        }
6655
6656        writeln!(self.writer)?;
6657        Ok(())
6658    }
6659
6660    /// マクロセクションを生成
6661    pub fn generate_macros(&mut self, result: &InferResult, known_symbols: &KnownSymbols) -> io::Result<()> {
6662        writeln!(self.writer, "// =============================================================================")?;
6663        writeln!(self.writer, "// Macro Functions")?;
6664        writeln!(self.writer, "// =============================================================================")?;
6665        writeln!(self.writer)?;
6666
6667        // 対象マクロを収集
6668        let macros: Vec<_> = result.infer_ctx.macros.iter()
6669            .filter(|(_, info)| self.should_include_macro(info))
6670            .collect();
6671        let included_set: HashSet<InternedStr> = macros.iter().map(|(n, _)| **n).collect();
6672
6673        // 依存順にソート(葉マクロ先頭)
6674        let sorted_names = self.topological_sort_macros(&macros);
6675
6676        // ── Phase 2 の解析結果を参照 ──
6677        // const/mut, bool 戻り値は Phase 2 (resolve_param_and_return_types) で確定済み
6678        // MacroInferInfo.const_pointer_positions, is_bool_return を参照する
6679        let mut callee_const_params: HashMap<InternedStr, HashSet<usize>> = HashMap::new();
6680        let mut bool_return_macros: HashSet<InternedStr> = HashSet::new();
6681        for (&name, info) in &result.infer_ctx.macros {
6682            if !info.const_pointer_positions.is_empty() {
6683                callee_const_params.insert(name, info.const_pointer_positions.clone());
6684            }
6685            if info.is_bool_return {
6686                bool_return_macros.insert(name);
6687            }
6688        }
6689        self.const_pointer_params = callee_const_params;
6690        self.bool_return_macros = bool_return_macros;
6691
6692        // 正常生成されたマクロを追跡
6693        let mut successfully_generated: HashSet<InternedStr> = HashSet::new();
6694
6695        for name in sorted_names {
6696            let info = result.infer_ctx.macros.get(&name).unwrap();
6697
6698            // ── apidoc skip_codegen 対象なら早期に [CODEGEN_SUPPRESSED] ──
6699            // Phase 2 (Step 4.4) で `info.apidoc_suppressed` が立っているので
6700            // それを参照する。reason 文字列は apidoc_patches から取得。
6701            if info.apidoc_suppressed {
6702                let name_str_for_patch = self.interner.get(name);
6703                let reason = result.apidoc_patches.skip_reason(name_str_for_patch)
6704                    .unwrap_or("apidoc skip_codegen");
6705                let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6706                writeln!(self.writer,
6707                    "// [CODEGEN_SUPPRESSED] {}{} - macro function (apidoc patch)",
6708                    name_str_for_patch, thx_info)?;
6709                writeln!(self.writer, "// Reason: {}", reason)?;
6710                writeln!(self.writer)?;
6711                self.report.record_skip(name_str_for_patch, format!(
6712                    "CODEGEN_SUPPRESSED (apidoc patch): {}", reason));
6713                continue;
6714            }
6715
6716            // ── カスケード検査 ──
6717            // called_functions のうち、生成対象だが生成に失敗した関数があれば
6718            // カスケード失敗。マクロ→マクロ依存と マクロ→inline 関数依存の両方を検査。
6719            // (uses ではなく called_functions を使う:uses はインライン展開された
6720            //   マクロも含むが、called_functions は AST 上の Call 式のみ)
6721            let unavailable_deps: Vec<String> = info.called_functions.iter()
6722                .filter(|called| {
6723                    // Case 1: マクロ→マクロ依存
6724                    if included_set.contains(called) {
6725                        return result.infer_ctx.macros.get(called)
6726                            .map(|u| u.is_parseable() && !u.is_unavailable_for_codegen())
6727                            .unwrap_or(false)
6728                            && !successfully_generated.contains(called);
6729                    }
6730                    // Case 2: マクロ→inline 関数依存
6731                    if result.inline_fn_dict.get(**called)
6732                        .map(|f| f.is_target)
6733                        .unwrap_or(false)
6734                    {
6735                        return !self.successfully_generated_inlines.contains(called);
6736                    }
6737                    false
6738                })
6739                .map(|called| self.interner.get(*called).to_string())
6740                .collect();
6741
6742            if !unavailable_deps.is_empty() {
6743                self.generate_macro_cascade_unavailable(info, &unavailable_deps)?;
6744                self.stats.macros_cascade_unavailable += 1;
6745                continue;
6746            }
6747
6748            // ── 既存のステータス判定と生成 ──
6749            let status = self.get_macro_status(info);
6750            match status {
6751                GenerateStatus::Success => {
6752                    // 新しい RustCodegen を使ってマクロを生成
6753                    let const_positions = self.const_pointer_params.get(&name)
6754                        .cloned().unwrap_or_default();
6755                    let is_bool = self.bool_return_macros.contains(&name);
6756                    let codegen = RustCodegen::new(self.interner, self.enum_dict, self.macro_ctx, self.bindings_info.clone(), known_symbols, result.rust_decl_dict.as_ref(), Some(&result.inline_fn_dict))
6757                        .with_perl_threaded(self.perl_threaded)
6758                        .with_dump_ast_for(self.config.dump_ast_for.clone())
6759                        .with_dump_types_for(self.config.dump_types_for.clone())
6760                        .with_fields_dict(&result.fields_dict)
6761                        .with_const_pointer_positions(const_positions)
6762                        .with_bool_return(is_bool, self.bool_return_macros.clone());
6763                    let generated = codegen.generate_macro(info);
6764
6765                    if generated.has_unresolved_names() {
6766                        // 未解決シンボルあり:コメントアウトして出力
6767                        let name_str = self.interner.get(info.name);
6768                        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6769                        writeln!(self.writer, "// [UNRESOLVED_NAMES] {}{} - macro function", name_str, thx_info)?;
6770                        writeln!(self.writer, "// Unresolved: {}", generated.unresolved_names.join(", "))?;
6771                        for line in generated.code.lines() {
6772                            writeln!(self.writer, "// {}", line)?;
6773                        }
6774                        writeln!(self.writer)?;
6775                        self.report.record_skip(name_str, format!(
6776                            "UNRESOLVED_NAMES: {}", generated.unresolved_names.join(", ")));
6777                        self.stats.macros_unresolved_names += 1;
6778                    } else if !generated.codegen_errors.is_empty() {
6779                        // codegen エラー検出:コメントアウトして問題点列挙
6780                        let name_str = self.interner.get(info.name);
6781                        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6782                        writeln!(self.writer, "// [CODEGEN_ERROR] {}{} - macro function", name_str, thx_info)?;
6783                        for err in &generated.codegen_errors {
6784                            writeln!(self.writer, "//   {}", err)?;
6785                        }
6786                        for line in generated.code.lines() {
6787                            writeln!(self.writer, "// {}", line)?;
6788                        }
6789                        writeln!(self.writer)?;
6790                        self.report.record_skip(name_str, format!(
6791                            "CODEGEN_ERROR: {}", generated.codegen_errors.join("; ")));
6792                    } else if generated.is_complete() {
6793                        // 完全な生成:そのまま出力
6794                        write!(self.writer, "{}", generated.code)?;
6795                        self.used_libc_fns.extend(generated.used_libc_fns.iter().cloned());
6796                        self.report.record_emit(self.interner.get(info.name));
6797                        self.stats.macros_success += 1;
6798                        successfully_generated.insert(name);
6799                    } else {
6800                        // 不完全な生成:コメントアウトして出力
6801                        let name_str = self.interner.get(info.name);
6802                        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6803                        writeln!(self.writer, "// [CODEGEN_INCOMPLETE] {}{} - macro function", name_str, thx_info)?;
6804                        for line in generated.code.lines() {
6805                            writeln!(self.writer, "// {}", line)?;
6806                        }
6807                        writeln!(self.writer)?;
6808                        self.report.record_skip(name_str, "CODEGEN_INCOMPLETE: type inference incomplete");
6809                        self.stats.macros_type_incomplete += 1;
6810                    }
6811                }
6812                GenerateStatus::ParseFailed => {
6813                    self.generate_macro_parse_failed(info)?;
6814                    self.report.record_skip(self.interner.get(info.name),
6815                        "PARSE_FAILED: macro body does not parse");
6816                    self.stats.macros_parse_failed += 1;
6817                }
6818                GenerateStatus::TypeIncomplete => {
6819                    self.generate_macro_type_incomplete(info, result)?;
6820                    self.report.record_skip(self.interner.get(info.name),
6821                        "TYPE_INCOMPLETE: parameter/return type could not be inferred");
6822                    self.stats.macros_type_incomplete += 1;
6823                }
6824                GenerateStatus::CallsUnavailable => {
6825                    // 原因を分類: 「実在しない関数を呼ぶ」vs「推移的に
6826                    // unavailable な依存先を呼ぶ」。前者なら [CALLS_UNAVAILABLE]、
6827                    // 後者なら [CASCADE_UNAVAILABLE] を出す。
6828                    let absent: Vec<&str> = info.called_functions.iter()
6829                        .filter(|fn_id| {
6830                            let fn_name = self.interner.get(**fn_id);
6831                            !self.is_function_available(**fn_id, fn_name, result)
6832                        })
6833                        .map(|fn_id| self.interner.get(*fn_id))
6834                        .collect();
6835                    if absent.is_empty() {
6836                        // 純粋に推移依存。unavailable な依存先を列挙
6837                        let cascade_deps: Vec<String> = info.called_functions.iter()
6838                            .filter(|fn_id| {
6839                                if let Some(m) = result.infer_ctx.macros.get(*fn_id) {
6840                                    return m.is_unavailable_for_codegen();
6841                                }
6842                                if result.inline_fn_dict.get(**fn_id).is_some() {
6843                                    return result.inline_fn_dict
6844                                        .is_unavailable_for_codegen(**fn_id);
6845                                }
6846                                false
6847                            })
6848                            .map(|fn_id| self.interner.get(*fn_id).to_string())
6849                            .collect();
6850                        self.generate_macro_cascade_unavailable(info, &cascade_deps)?;
6851                        self.stats.macros_cascade_unavailable += 1;
6852                    } else {
6853                        let mut absent_sorted: Vec<String> =
6854                            absent.iter().map(|s| s.to_string()).collect();
6855                        absent_sorted.sort();
6856                        self.generate_macro_calls_unavailable(info, result)?;
6857                        self.report.record_skip(self.interner.get(info.name), format!(
6858                            "CALLS_UNAVAILABLE: calls unavailable function(s): {}",
6859                            absent_sorted.join(", ")));
6860                        self.stats.macros_calls_unavailable += 1;
6861                    }
6862                }
6863                GenerateStatus::ContainsGoto => {
6864                    let name_str = self.interner.get(info.name);
6865                    writeln!(self.writer, "// [CONTAINS_GOTO] {} - excluded (contains goto)", name_str)?;
6866                    writeln!(self.writer)?;
6867                    self.report.record_skip(name_str, "CONTAINS_GOTO: excluded (contains goto)");
6868                }
6869                GenerateStatus::GenericUnsupported => {
6870                    let name_str = self.interner.get(info.name);
6871                    let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6872                    writeln!(self.writer, "// [GENERIC_UNSUPPORTED] {}{} - Rust cannot cast to generic type T", name_str, thx_info)?;
6873                    // コメントアウトしたコードを出力
6874                    let const_positions = self.const_pointer_params.get(&name)
6875                        .cloned().unwrap_or_default();
6876                    let is_bool = self.bool_return_macros.contains(&name);
6877                    let codegen = RustCodegen::new(self.interner, self.enum_dict, self.macro_ctx, self.bindings_info.clone(), known_symbols, result.rust_decl_dict.as_ref(), Some(&result.inline_fn_dict))
6878                        .with_perl_threaded(self.perl_threaded)
6879                        .with_fields_dict(&result.fields_dict)
6880                        .with_const_pointer_positions(const_positions)
6881                        .with_bool_return(is_bool, self.bool_return_macros.clone());
6882                    let generated = codegen.generate_macro(info);
6883                    for line in generated.code.lines() {
6884                        writeln!(self.writer, "// {}", line)?;
6885                    }
6886                    writeln!(self.writer)?;
6887                    self.report.record_skip(self.interner.get(info.name),
6888                        "GENERIC_UNSUPPORTED: Rust cannot cast to generic type T");
6889                    self.stats.macros_generic_unsupported += 1;
6890                }
6891                GenerateStatus::Skip => {
6892                    // 出力なし。require 検証用に理由だけ記録する
6893                    self.report.record_skip(self.interner.get(info.name),
6894                        "SKIP: excluded from code generation");
6895                }
6896            }
6897        }
6898
6899        Ok(())
6900    }
6901
6902    /// マクロを依存順にソート(葉マクロ先頭、循環はアルファベット順で末尾)
6903    ///
6904    /// Kahn's algorithm を使用。`info.uses` の関係から DAG を構築し、
6905    fn topological_sort_macros(
6906        &self,
6907        macros: &[(&InternedStr, &MacroInferInfo)],
6908    ) -> Vec<InternedStr> {
6909        use std::collections::VecDeque;
6910
6911        let macro_set: HashSet<InternedStr> = macros.iter().map(|(n, _)| **n).collect();
6912
6913        // 入次数マップと逆隣接リスト(dependency → dependents)を構築
6914        let mut in_degree: HashMap<InternedStr, usize> = HashMap::new();
6915        let mut dependents: HashMap<InternedStr, Vec<InternedStr>> = HashMap::new();
6916
6917        for (name, _) in macros {
6918            in_degree.insert(**name, 0);
6919        }
6920
6921        for (name, info) in macros {
6922            for used in &info.uses {
6923                if macro_set.contains(used) {
6924                    // name が used に依存 → used から name への辺
6925                    *in_degree.entry(**name).or_insert(0) += 1;
6926                    dependents.entry(*used).or_default().push(**name);
6927                }
6928            }
6929        }
6930
6931        // 入次数 0 のマクロをキューに投入(アルファベット順で安定化)
6932        let mut queue: VecDeque<InternedStr> = {
6933            let mut zeros: Vec<_> = in_degree.iter()
6934                .filter(|(_, deg)| **deg == 0)
6935                .map(|(name, _)| *name)
6936                .collect();
6937            zeros.sort_by_key(|n| self.interner.get(*n));
6938            zeros.into_iter().collect()
6939        };
6940
6941        let mut result = Vec::with_capacity(macros.len());
6942
6943        while let Some(name) = queue.pop_front() {
6944            result.push(name);
6945            if let Some(deps) = dependents.get(&name) {
6946                // 依存先の入次数を減算
6947                let mut newly_ready: Vec<InternedStr> = Vec::new();
6948                for dep in deps {
6949                    if let Some(deg) = in_degree.get_mut(dep) {
6950                        *deg -= 1;
6951                        if *deg == 0 {
6952                            newly_ready.push(*dep);
6953                        }
6954                    }
6955                }
6956                // アルファベット順で安定化
6957                newly_ready.sort_by_key(|n| self.interner.get(*n));
6958                for n in newly_ready {
6959                    queue.push_back(n);
6960                }
6961            }
6962        }
6963
6964        // 残り(循環メンバー)をアルファベット順で末尾に追加
6965        if result.len() < macros.len() {
6966            let result_set: HashSet<_> = result.iter().copied().collect();
6967            let mut remaining: Vec<_> = macro_set.iter()
6968                .filter(|n| !result_set.contains(n))
6969                .copied()
6970                .collect();
6971            remaining.sort_by_key(|n| self.interner.get(*n));
6972            result.extend(remaining);
6973        }
6974
6975        result
6976    }
6977
6978    /// カスケード依存によるコメントアウト出力
6979    fn generate_macro_cascade_unavailable(
6980        &mut self,
6981        info: &MacroInferInfo,
6982        unavailable_deps: &[String],
6983    ) -> io::Result<()> {
6984        let name_str = self.interner.get(info.name);
6985        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
6986        let mut deps: Vec<&String> = unavailable_deps.iter().collect();
6987        deps.sort(); // 列挙順の決定化
6988        let deps: Vec<&str> = deps.iter().map(|s| s.as_str()).collect();
6989        writeln!(self.writer,
6990            "// [CASCADE_UNAVAILABLE] {}{} - dependency not generated: {}",
6991            name_str, thx_info, deps.join(", "))?;
6992        writeln!(self.writer)?;
6993        self.report.record_skip(name_str, format!(
6994            "CASCADE_UNAVAILABLE: dependency not generated: {}", deps.join(", ")));
6995        Ok(())
6996    }
6997
6998    /// マクロを出力対象にするかどうか
6999    fn should_include_macro(&self, info: &MacroInferInfo) -> bool {
7000        // ターゲットでなければスキップ
7001        if !info.is_target {
7002            return false;
7003        }
7004
7005        // 本体がなければスキップ
7006        if !info.has_body {
7007            return false;
7008        }
7009
7010        // 関数形式マクロのみ含める(オブジェクトマクロは常にインライン展開される)
7011        info.is_function
7012    }
7013
7014    /// マクロの生成ステータスを判定
7015    fn get_macro_status(&self, info: &MacroInferInfo) -> GenerateStatus {
7016        // 利用不可関数を呼び出すマクロは CallsUnavailable
7017        if info.calls_unavailable {
7018            return GenerateStatus::CallsUnavailable;
7019        }
7020
7021        // ジェネリクス型パラメータを含むマクロは生成不可
7022        // Rust の as T キャストや T + u32 演算が不可
7023        if !info.generic_type_params.is_empty() {
7024            return GenerateStatus::GenericUnsupported;
7025        }
7026
7027        match &info.parse_result {
7028            ParseResult::Unparseable(_) => GenerateStatus::ParseFailed,
7029            ParseResult::Statement(items) => {
7030                // goto を含むマクロは除外
7031                if block_items_contain_goto(items) {
7032                    return GenerateStatus::ContainsGoto;
7033                }
7034                if info.is_fully_confirmed() {
7035                    GenerateStatus::Success
7036                } else {
7037                    GenerateStatus::TypeIncomplete
7038                }
7039            }
7040            ParseResult::Expression(_) => {
7041                if info.is_fully_confirmed() {
7042                    GenerateStatus::Success
7043                } else {
7044                    GenerateStatus::TypeIncomplete
7045                }
7046            }
7047        }
7048    }
7049
7050    /// パース失敗マクロをコメント出力
7051    fn generate_macro_parse_failed(&mut self, info: &MacroInferInfo) -> io::Result<()> {
7052        let name_str = self.interner.get(info.name);
7053
7054        // パラメータリストを構築
7055        let params_str = if info.is_function {
7056            let params: Vec<_> = info.params.iter()
7057                .map(|p| self.interner.get(p.name).to_string())
7058                .collect();
7059            format!("({})", params.join(", "))
7060        } else {
7061            String::new()
7062        };
7063
7064        writeln!(self.writer, "// [PARSE_FAILED] {}{}", name_str, params_str)?;
7065
7066        // エラーメッセージがあれば出力
7067        if let ParseResult::Unparseable(Some(err_msg)) = &info.parse_result {
7068            writeln!(self.writer, "// Error: {}", err_msg)?;
7069        }
7070
7071        // TODO: トークン列の S 式出力(Phase 2 で詳細実装)
7072        writeln!(self.writer, "// (tokens not available in parsed form)")?;
7073        writeln!(self.writer)?;
7074
7075        Ok(())
7076    }
7077
7078    /// 利用不可関数呼び出しマクロをコメント出力
7079    fn generate_macro_calls_unavailable(&mut self, info: &MacroInferInfo, result: &InferResult) -> io::Result<()> {
7080        let name_str = self.interner.get(info.name);
7081
7082        // パラメータリストを構築
7083        let params_str = if info.is_function {
7084            let params: Vec<_> = info.params.iter()
7085                .map(|p| self.interner.get(p.name).to_string())
7086                .collect();
7087            format!("({})", params.join(", "))
7088        } else {
7089            String::new()
7090        };
7091
7092        // THX 情報
7093        let thx_info = if info.is_thx_dependent { " [THX]" } else { "" };
7094
7095        writeln!(self.writer, "// [CALLS_UNAVAILABLE] {}{}{} - calls unavailable function(s)", name_str, params_str, thx_info)?;
7096
7097        // 利用不可関数を特定して出力
7098        let unavailable_fns: Vec<_> = info.called_functions.iter()
7099            .filter(|&fn_id| {
7100                let fn_name = self.interner.get(*fn_id);
7101                // bindings.rs にもマクロにも存在しない関数を検出
7102                !self.is_function_available(*fn_id, fn_name, result)
7103            })
7104            .map(|fn_id| self.interner.get(*fn_id))
7105            .collect();
7106
7107        if !unavailable_fns.is_empty() {
7108            let mut unavailable_fns = unavailable_fns;
7109            unavailable_fns.sort(); // 列挙順の決定化
7110            writeln!(self.writer, "// Unavailable: {}", unavailable_fns.join(", "))?;
7111        }
7112
7113        writeln!(self.writer)?;
7114
7115        Ok(())
7116    }
7117
7118    /// 関数が利用可能かチェック
7119    fn is_function_available(&self, fn_id: crate::InternedStr, fn_name: &str, result: &InferResult) -> bool {
7120        // マクロとして存在する場合はOK
7121        if result.infer_ctx.macros.contains_key(&fn_id) {
7122            return true;
7123        }
7124
7125        // bindings.rs に存在する場合はOK
7126        if let Some(rust_decl_dict) = &result.rust_decl_dict {
7127            if rust_decl_dict.fns.contains_key(fn_name) {
7128                return true;
7129            }
7130        }
7131
7132        // インライン関数として存在する場合はOK
7133        if result.inline_fn_dict.get(fn_id).is_some() {
7134            return true;
7135        }
7136
7137        // ビルトイン関数リスト(macro_infer.rs と同じ)
7138        let builtin_fns = [
7139            "__builtin_expect",
7140            "__builtin_offsetof",
7141            "offsetof",
7142            "__builtin_types_compatible_p",
7143            "__builtin_constant_p",
7144            "__builtin_choose_expr",
7145            "__builtin_unreachable",
7146            "__builtin_trap",
7147            "__builtin_assume",
7148            "__builtin_bswap16",
7149            "__builtin_bswap32",
7150            "__builtin_bswap64",
7151            "__builtin_popcount",
7152            "__builtin_clz",
7153            "__builtin_ctz",
7154            "pthread_mutex_lock",
7155            "pthread_mutex_unlock",
7156            "pthread_rwlock_rdlock",
7157            "pthread_rwlock_wrlock",
7158            "pthread_rwlock_unlock",
7159            "memchr",
7160            "memcpy",
7161            "memmove",
7162            "memset",
7163            "strlen",
7164            "strcmp",
7165            "strncmp",
7166            "strcpy",
7167            "strncpy",
7168            "ASSERT_IS_LITERAL",
7169            "ASSERT_IS_PTR",
7170            "ASSERT_NOT_PTR",
7171        ];
7172
7173        if builtin_fns.contains(&fn_name) {
7174            return true;
7175        }
7176
7177        false
7178    }
7179
7180    /// 型推論失敗マクロをコメント出力
7181    fn generate_macro_type_incomplete(&mut self, info: &MacroInferInfo, result: &InferResult) -> io::Result<()> {
7182        let name_str = self.interner.get(info.name);
7183
7184        // パラメータリストを構築
7185        let params_str = if info.is_function {
7186            let params: Vec<_> = info.params.iter()
7187                .map(|p| self.interner.get(p.name).to_string())
7188                .collect();
7189            format!("({})", params.join(", "))
7190        } else {
7191            String::new()
7192        };
7193
7194        writeln!(self.writer, "// [TYPE_INCOMPLETE] {}{}", name_str, params_str)?;
7195
7196        // 型推論状態を出力
7197        writeln!(self.writer, "// Args status: {:?}, Return status: {:?}",
7198            info.args_infer_status, info.return_infer_status)?;
7199
7200        // 型付 S 式を出力
7201        writeln!(self.writer, "// Typed S-expression:")?;
7202        self.write_typed_sexp_comment(info, result)?;
7203
7204        writeln!(self.writer)?;
7205        Ok(())
7206    }
7207
7208    /// 型付 S 式をコメントとして出力
7209    fn write_typed_sexp_comment(&mut self, info: &MacroInferInfo, _result: &InferResult) -> io::Result<()> {
7210        match &info.parse_result {
7211            ParseResult::Expression(expr) => {
7212                self.write_expr_sexp_comment(expr, info, "//   ")?;
7213            }
7214            ParseResult::Statement(block_items) => {
7215                for item in block_items {
7216                    if let BlockItem::Stmt(stmt) = item {
7217                        self.write_stmt_sexp_comment(stmt, info, "//   ")?;
7218                    }
7219                }
7220            }
7221            ParseResult::Unparseable(_) => {
7222                writeln!(self.writer, "//   (unparseable)")?;
7223            }
7224        }
7225        Ok(())
7226    }
7227
7228    /// 式の S 式をコメントとして出力
7229    fn write_expr_sexp_comment(&mut self, expr: &Expr, info: &MacroInferInfo, prefix: &str) -> io::Result<()> {
7230        // 簡易的な S 式出力
7231        let mut buf = Vec::new();
7232        {
7233            let mut printer = SexpPrinter::new(&mut buf, self.interner);
7234            let _ = printer.print_expr(expr);
7235        }
7236
7237        // 型情報を追加
7238        let sexp_str = String::from_utf8_lossy(&buf);
7239        let type_info = self.get_expr_type_info(expr, info);
7240
7241        // 各行にプレフィックスを付けて出力
7242        for line in sexp_str.lines() {
7243            writeln!(self.writer, "{}{}", prefix, line)?;
7244        }
7245        if !type_info.is_empty() {
7246            writeln!(self.writer, "{} :type {}", prefix, type_info)?;
7247        }
7248
7249        Ok(())
7250    }
7251
7252    /// 文の S 式をコメントとして出力
7253    fn write_stmt_sexp_comment(&mut self, stmt: &Stmt, _info: &MacroInferInfo, prefix: &str) -> io::Result<()> {
7254        let mut buf = Vec::new();
7255        {
7256            let mut printer = SexpPrinter::new(&mut buf, self.interner);
7257            let _ = printer.print_stmt(stmt);
7258        }
7259
7260        let sexp_str = String::from_utf8_lossy(&buf);
7261        for line in sexp_str.lines() {
7262            writeln!(self.writer, "{}{}", prefix, line)?;
7263        }
7264
7265        Ok(())
7266    }
7267
7268    /// 式の型情報を取得
7269    fn get_expr_type_info(&self, expr: &Expr, info: &MacroInferInfo) -> String {
7270        // TypeEnv から型制約を取得
7271        if let Some(constraints) = info.type_env.expr_constraints.get(&expr.id) {
7272            if let Some(first) = constraints.first() {
7273                return first.ty.to_display_string(self.interner);
7274            }
7275        }
7276        "<unknown>".to_string()
7277    }
7278}
7279
7280#[cfg(test)]
7281mod codegen_report_tests {
7282    use super::*;
7283
7284    fn sample_report() -> CodegenReport {
7285        let mut report = CodegenReport::default();
7286        report.record_emit("CvFILE");
7287        report.record_emit("CvROOT");
7288        report.record_skip("CvSTART", "CASCADE_UNAVAILABLE: dependency not generated: CvROOT");
7289        report
7290    }
7291
7292    #[test]
7293    fn test_check_required_empty_list_is_noop() {
7294        let report = sample_report();
7295        assert!(report.check_required(&[]).is_ok());
7296    }
7297
7298    #[test]
7299    fn test_check_required_emitted_names_pass() {
7300        let report = sample_report();
7301        let required = vec!["CvFILE".to_string(), "CvROOT".to_string()];
7302        assert!(report.check_required(&required).is_ok());
7303    }
7304
7305    #[test]
7306    fn test_check_required_skipped_name_reports_recorded_reason() {
7307        let report = sample_report();
7308        let required = vec!["CvSTART".to_string()];
7309        let err = report.check_required(&required).unwrap_err();
7310        assert_eq!(err.violations.len(), 1);
7311        assert_eq!(err.violations[0].name, "CvSTART");
7312        assert!(err.violations[0].reason.contains("CASCADE_UNAVAILABLE"));
7313        // Display にも名前と理由が現れる
7314        let msg = err.to_string();
7315        assert!(msg.contains("CvSTART"));
7316        assert!(msg.contains("CASCADE_UNAVAILABLE"));
7317    }
7318
7319    #[test]
7320    fn test_check_required_unknown_name_reports_not_a_target() {
7321        let report = sample_report();
7322        let required = vec!["NoSuchFunction".to_string()];
7323        let err = report.check_required(&required).unwrap_err();
7324        assert_eq!(err.violations.len(), 1);
7325        assert!(err.violations[0].reason.contains("not a codegen target"));
7326    }
7327
7328    #[test]
7329    fn test_check_required_collects_all_violations() {
7330        let report = sample_report();
7331        let required = vec![
7332            "CvFILE".to_string(),        // emitted → OK
7333            "CvSTART".to_string(),       // skipped → 違反
7334            "NoSuchFunction".to_string(), // 不在 → 違反
7335        ];
7336        let err = report.check_required(&required).unwrap_err();
7337        assert_eq!(err.violations.len(), 2);
7338    }
7339}