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