Skip to main content

libperl_macrogen/
rust_codegen.rs

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