rusty_cpp/parser/
ast_visitor.rs

1use clang::{Entity, EntityKind, Type, TypeKind};
2use crate::debug_println;
3
4/// Check if a C++ method is deleted (= delete) or defaulted (= default)
5/// These special member functions don't count as regular methods for @interface validation.
6///
7/// Uses libclang's native APIs:
8/// - `is_defaulted()` for `= default` detection (libclang 3.9+)
9/// - `clang_CXXMethod_isDeleted()` for `= delete` detection (libclang 16.0+)
10///
11/// No source file parsing needed - works with temp files and multi-line declarations.
12fn is_deleted_or_defaulted_method(entity: &Entity) -> bool {
13    // Check for = default using clang crate's wrapper
14    if entity.is_defaulted() {
15        debug_println!("DEBUG PARSE: Method {:?} is defaulted via libclang", entity.get_name());
16        return true;
17    }
18
19    // Check for = delete using availability
20    // Deleted methods have Unavailable availability
21    if entity.get_availability() == clang::Availability::Unavailable {
22        debug_println!("DEBUG PARSE: Method {:?} is deleted (Unavailable)", entity.get_name());
23        return true;
24    }
25
26    // Fallback: Check for = delete using libclang 16+ native API
27    if is_deleted_via_libclang(entity) {
28        debug_println!("DEBUG PARSE: Method {:?} is deleted via libclang FFI", entity.get_name());
29        return true;
30    }
31
32    false
33}
34
35/// Check if method is deleted (= delete) using libclang's native API.
36///
37/// Uses clang_CXXMethod_isDeleted from libclang 16+.
38/// The clang crate doesn't wrap this function, so we call clang-sys directly.
39fn is_deleted_via_libclang(entity: &Entity) -> bool {
40    // Entity layout: { raw: CXCursor, tu: &'tu TranslationUnit<'tu> }
41    // We extract the CXCursor (first field) to call the FFI function directly.
42    //
43    // SAFETY:
44    // - Entity is repr(Rust), but raw is the first field
45    // - CXCursor is Copy, Clone
46    // - We're only reading, not modifying
47    //
48    // Use transmute_copy to extract the raw cursor bytes
49    let raw_cursor: clang_sys::CXCursor = unsafe {
50        // CXCursor is 32 bytes (kind: c_int, xdata: c_int, data: [*const c_void; 3])
51        // Entity starts with the raw CXCursor field
52        std::mem::transmute_copy(entity)
53    };
54
55    // Call the libclang 16+ function directly
56    let result = unsafe {
57        clang_sys::clang_CXXMethod_isDeleted(raw_cursor)
58    };
59
60    result != 0
61}
62
63/// Check if a function name is std::move, rusty::move, or a namespace-qualified move
64///
65/// rusty::move provides Rust-like move semantics where moving a reference
66/// invalidates the reference variable itself (not just the underlying object).
67fn is_move_function(name: &str) -> bool {
68    name == "move"
69        || name == "std::move"
70        || name == "rusty::move"
71        || name.ends_with("::move")
72}
73
74/// Determine the kind of move function (std::move vs rusty::move)
75fn get_move_kind(name: &str) -> MoveKind {
76    if name == "rusty::move" || name.ends_with("::rusty::move") {
77        MoveKind::RustyMove
78    } else {
79        // std::move, move, or any other ::move variant is treated as std::move
80        MoveKind::StdMove
81    }
82}
83
84/// Check if a function name is std::forward or a namespace-qualified forward
85fn is_forward_function(name: &str) -> bool {
86    name == "forward" || name == "std::forward" || name.ends_with("::forward")
87}
88
89/// Check if an entity represents a call to an overloaded operator->
90///
91/// Key insight: If the entity is a call to "operator->", it means the type has
92/// an overloaded operator->. This is the definition of a smart pointer.
93/// Raw pointers use the built-in -> operator which does NOT create a CallExpr.
94///
95/// So the detection is simple:
96/// - If we see a CallExpr/UnexposedExpr named "operator->", it's a smart pointer
97/// - Raw pointers never create such a call
98fn has_overloaded_arrow_operator(entity: &Entity) -> bool {
99    // Check if the entity's name is "operator->"
100    // This indicates an overloaded operator-> was called, meaning it's a smart pointer
101    if let Some(name) = entity.get_name() {
102        if name == "operator->" {
103            debug_println!("DEBUG: Found overloaded operator-> call");
104            return true;
105        }
106    }
107
108    // For nested cases (like method calls), check children recursively
109    // e.g., box->get_value() has nested operator-> calls
110    for child in entity.get_children() {
111        if let Some(child_name) = child.get_name() {
112            if child_name == "operator->" {
113                debug_println!("DEBUG: Found overloaded operator-> in child");
114                return true;
115            }
116        }
117    }
118
119    false
120}
121
122/// Check if an entity has an @unsafe annotation by reading source file
123fn check_for_unsafe_annotation(entity: &Entity) -> bool {
124    use std::fs::File;
125    use std::io::{BufRead, BufReader};
126
127    // Try get_comment() first (works for some entity types)
128    if let Some(comment) = entity.get_comment() {
129        if comment.contains("@unsafe") {
130            return true;
131        }
132    }
133
134    // For CompoundStmt and other entities, check the source file directly
135    let location = match entity.get_location() {
136        Some(loc) => loc,
137        None => return false,
138    };
139
140    let file_location = location.get_file_location();
141    let file = match file_location.file {
142        Some(f) => f,
143        None => return false,
144    };
145
146    let file_path = file.get_path();
147    let block_line = file_location.line as usize;
148
149    // Read the source file and check the line before the block
150    let file_handle = match File::open(&file_path) {
151        Ok(f) => f,
152        Err(_) => return false,
153    };
154
155    let reader = BufReader::new(file_handle);
156    let mut current_line = 0;
157    let mut prev_line = String::new();
158
159    for line_result in reader.lines() {
160        current_line += 1;
161        let line = match line_result {
162            Ok(l) => l,
163            Err(_) => continue,
164        };
165
166        // Check if we're at the block's line
167        if current_line == block_line {
168            // Check the previous line for @unsafe annotation
169            let trimmed = prev_line.trim();
170            if trimmed.starts_with("//") && trimmed.contains("@unsafe") {
171                debug_println!("DEBUG UNSAFE: Found @unsafe annotation for block at line {}", block_line);
172                return true;
173            }
174            // Also check for /* @unsafe */ style comments
175            if trimmed.contains("/*") && trimmed.contains("@unsafe") && trimmed.contains("*/") {
176                debug_println!("DEBUG UNSAFE: Found @unsafe annotation for block at line {}", block_line);
177                return true;
178            }
179            return false;
180        }
181
182        prev_line = line;
183    }
184
185    false
186}
187
188/// Check if a field declaration has the 'mutable' keyword
189/// Read the source code around the declaration to detect 'mutable'
190fn check_for_mutable_keyword(entity: &Entity) -> bool {
191    use std::fs::File;
192    use std::io::{BufRead, BufReader};
193
194    let location = match entity.get_location() {
195        Some(loc) => loc,
196        None => return false,
197    };
198
199    let file_location = location.get_file_location();
200    let file = match file_location.file {
201        Some(f) => f,
202        None => return false,
203    };
204
205    let file_path = file.get_path();
206    let decl_line = file_location.line as usize;
207
208    // Read the source file and check the line with the declaration
209    let file_handle = match File::open(&file_path) {
210        Ok(f) => f,
211        Err(_) => return false,
212    };
213
214    let reader = BufReader::new(file_handle);
215    let mut current_line = 0;
216
217    for line_result in reader.lines() {
218        current_line += 1;
219        let line = match line_result {
220            Ok(l) => l,
221            Err(_) => continue,
222        };
223
224        // Check if we're at the declaration line
225        if current_line == decl_line {
226            // Check if the line contains the 'mutable' keyword
227            // Look for word boundary to avoid matching "immutable" or similar
228            let trimmed = line.trim();
229            let has_mutable = trimmed.starts_with("mutable ") ||
230                             trimmed.contains(" mutable ") ||
231                             (trimmed == "mutable");
232
233            debug_println!("DEBUG MUTABLE: Line {}: '{}' -> has_mutable = {}",
234                decl_line, trimmed, has_mutable);
235
236            return has_mutable;
237        }
238    }
239
240    false
241}
242
243/// Get the qualified name of an entity (including namespace/class context)
244pub fn get_qualified_name(entity: &Entity) -> String {
245    let simple_name = entity.get_name().unwrap_or_else(|| "anonymous".to_string());
246
247    // Try to build qualified name by walking up the semantic parents
248    let mut parts = vec![simple_name.clone()];
249    let mut current = entity.get_semantic_parent();
250
251    while let Some(parent) = current {
252        match parent.get_kind() {
253            EntityKind::Namespace | EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate => {
254                if let Some(parent_name) = parent.get_name() {
255                    if !parent_name.is_empty() {
256                        parts.push(parent_name);
257                    }
258                }
259            }
260            _ => {}
261        }
262        current = parent.get_semantic_parent();
263    }
264
265    // Reverse to get the correct order (namespace::class::method)
266    parts.reverse();
267
268    // Join with :: but skip if we only have the simple name
269    if parts.len() > 1 {
270        parts.join("::")
271    } else {
272        simple_name
273    }
274}
275
276/// Extract template type parameters from a template entity
277///
278/// For `template<typename T, typename U>`, this returns ["T", "U"]
279/// Works with ClassTemplateDecl and FunctionTemplateDecl
280pub fn extract_template_parameters(entity: &Entity) -> Vec<String> {
281    use clang::EntityVisitResult;
282
283    let mut params = Vec::new();
284
285    // Visit direct children to find TemplateTypeParameter or NonTypeTemplateParameter
286    entity.visit_children(|child, _| {
287        match child.get_kind() {
288            EntityKind::TemplateTypeParameter | EntityKind::NonTypeTemplateParameter => {
289                if let Some(name) = child.get_name() {
290                    debug_println!("TEMPLATE: Found type parameter: {}", name);
291                    params.push(name);
292                }
293            }
294            _ => {}
295        }
296        EntityVisitResult::Continue
297    });
298
299    params
300}
301
302// Phase 3: Class template representation
303#[derive(Debug, Clone)]
304pub struct Class {
305    pub name: String,
306    pub template_parameters: Vec<String>,  // e.g., ["T", "Args"] for template<typename T, typename... Args>
307    pub is_template: bool,
308    pub members: Vec<Variable>,            // Member fields
309    pub methods: Vec<Function>,            // Member methods
310    pub base_classes: Vec<String>,         // Base class names (may contain packs like "Bases...")
311    pub location: SourceLocation,
312    // RAII Phase 2: Track if class has a destructor
313    pub has_destructor: bool,              // True if class has ~ClassName()
314    // Inheritance safety: Interface-related fields
315    pub is_interface: bool,                // Has @interface annotation
316    pub has_virtual_destructor: bool,      // virtual ~Class() or virtual ~Class() = default
317    pub destructor_is_defaulted: bool,     // True if destructor is = default
318    pub all_methods_pure_virtual: bool,    // All methods are = 0 (pure virtual)
319    pub has_non_virtual_methods: bool,     // Has any non-virtual methods (excluding destructor)
320    pub safety_annotation: Option<crate::parser::safety_annotations::SafetyMode>, // @safe or @unsafe on class
321    // Copy semantics: @safe classes should not have copy operations (Rust-like move semantics)
322    pub has_copy_constructor: bool,        // True if class has ClassName(const ClassName&)
323    pub has_copy_assignment: bool,         // True if class has operator=(const ClassName&)
324    pub copy_constructor_deleted: bool,    // True if copy constructor is explicitly deleted
325    pub copy_assignment_deleted: bool,     // True if copy assignment is explicitly deleted
326}
327
328#[derive(Debug, Clone)]
329pub struct CppAst {
330    pub functions: Vec<Function>,
331    pub global_variables: Vec<Variable>,
332    pub classes: Vec<Class>,  // Phase 3: Track template classes
333}
334
335impl CppAst {
336    pub fn new() -> Self {
337        Self {
338            functions: Vec::new(),
339            global_variables: Vec::new(),
340            classes: Vec::new(),  // Phase 3
341        }
342    }
343}
344
345#[derive(Debug, Clone, PartialEq)]
346pub enum MethodQualifier {
347    Const,        // const method (like Rust's &self)
348    NonConst,     // regular method (like Rust's &mut self)
349    RvalueRef,    // && qualified method (like Rust's self)
350}
351
352#[derive(Debug, Clone)]
353pub struct Function {
354    pub name: String,
355    pub parameters: Vec<Variable>,
356    #[allow(dead_code)]
357    pub return_type: String,
358    #[allow(dead_code)]
359    pub body: Vec<Statement>,
360    #[allow(dead_code)]
361    pub location: SourceLocation,
362    // Method information
363    pub is_method: bool,
364    pub method_qualifier: Option<MethodQualifier>,
365    pub class_name: Option<String>,
366    // Template information
367    pub template_parameters: Vec<String>,  // e.g., ["T", "U"] for template<typename T, typename U>
368    // Safety annotation for method safety contract checking
369    pub safety_annotation: Option<crate::parser::safety_annotations::SafetyMode>,
370    pub has_explicit_safety_annotation: bool,  // true if annotation was in source code
371}
372
373#[derive(Debug, Clone)]
374pub struct Variable {
375    pub name: String,
376    pub type_name: String,
377    pub is_reference: bool,
378    #[allow(dead_code)]
379    pub is_pointer: bool,
380    pub is_const: bool,
381    pub is_unique_ptr: bool,
382    #[allow(dead_code)]
383    pub is_shared_ptr: bool,
384    pub is_static: bool,
385    pub is_mutable: bool,                      // C++ mutable keyword (for interior mutability)
386    #[allow(dead_code)]
387    pub location: SourceLocation,
388    // Variadic template support (Phase 1)
389    pub is_pack: bool,                         // Is this a parameter pack (e.g., Args... args)?
390    pub pack_element_type: Option<String>,     // Type of pack elements (e.g., "Args&&" from "Args&&...")
391}
392
393#[derive(Debug, Clone)]
394#[allow(dead_code)]
395pub enum Statement {
396    VariableDecl(Variable),
397    Assignment {
398        lhs: Expression,  // Changed to Expression to support dereference: *ptr = value
399        rhs: Expression,
400        location: SourceLocation,
401    },
402    ReferenceBinding {
403        name: String,
404        target: Expression,
405        is_mutable: bool,
406        location: SourceLocation,
407    },
408    Return(Option<Expression>),
409    FunctionCall {
410        name: String,
411        args: Vec<Expression>,
412        location: SourceLocation,
413    },
414    Block(Vec<Statement>),
415    // Scope markers
416    EnterScope,
417    ExitScope,
418    // Loop markers
419    EnterLoop,
420    ExitLoop,
421    // Safety markers
422    EnterUnsafe,
423    ExitUnsafe,
424    // Conditional statements
425    If {
426        condition: Expression,
427        then_branch: Vec<Statement>,
428        else_branch: Option<Vec<Statement>>,
429        location: SourceLocation,
430    },
431    // Expression statements (e.g., standalone dereference, method calls)
432    ExpressionStatement {
433        expr: Expression,
434        location: SourceLocation,
435    },
436    // Phase 2: Pack expansion statement (fold expressions, pack usage)
437    PackExpansion {
438        pack_name: String,           // Name of the pack being expanded (e.g., "args")
439        operation: String,           // Type of operation: "forward", "move", "use"
440        location: SourceLocation,
441    },
442    // Lambda expression with captures (for safety checking)
443    LambdaExpr {
444        captures: Vec<LambdaCaptureKind>,
445        location: SourceLocation,
446    },
447}
448
449/// Represents a lambda capture
450#[derive(Debug, Clone)]
451pub enum LambdaCaptureKind {
452    /// [&] - default reference capture
453    DefaultRef,
454    /// [=] - default copy capture
455    DefaultCopy,
456    /// [&x] - explicit reference capture
457    ByRef(String),
458    /// [x] - explicit copy capture
459    ByCopy(String),
460    /// [x = expr] - init capture (includes move captures)
461    Init { name: String, is_move: bool },
462    /// [this] - captures this pointer
463    This,
464    /// [*this] - captures this by copy (C++17)
465    ThisCopy,
466}
467
468/// Indicates which move function was used
469#[derive(Debug, Clone, PartialEq, Eq)]
470pub enum MoveKind {
471    /// std::move - standard C++ move, unsafe for references in @safe code
472    StdMove,
473    /// rusty::move - Rust-like move semantics, safe for all types
474    RustyMove,
475}
476
477#[derive(Debug, Clone)]
478#[allow(dead_code)]
479pub enum Expression {
480    Variable(String),
481    Move {
482        inner: Box<Expression>,
483        kind: MoveKind,
484    },
485    Dereference(Box<Expression>),
486    AddressOf(Box<Expression>),
487    FunctionCall {
488        name: String,
489        args: Vec<Expression>,
490    },
491    Literal(String),
492    /// String literal expression ("hello", L"wide", u8"utf8", etc.)
493    /// String literals are safe in @safe code because they have static lifetime.
494    /// They cannot dangle because they're stored in .rodata (read-only data segment).
495    StringLiteral(String),
496    BinaryOp {
497        left: Box<Expression>,
498        op: String,
499        right: Box<Expression>,
500    },
501    // NEW: Member access (obj.field)
502    MemberAccess {
503        object: Box<Expression>,
504        field: String,
505    },
506    // Lambda expression with captures
507    Lambda {
508        captures: Vec<LambdaCaptureKind>,
509    },
510    // C++ cast expression (static_cast, dynamic_cast, reinterpret_cast, const_cast, C-style)
511    // All casts are considered unsafe operations in @safe code
512    Cast(Box<Expression>),
513}
514
515#[derive(Debug, Clone)]
516pub struct SourceLocation {
517    #[allow(dead_code)]
518    pub file: String,
519    #[allow(dead_code)]
520    pub line: u32,
521    #[allow(dead_code)]
522    pub column: u32,
523}
524
525pub fn extract_function(entity: &Entity) -> Function {
526    use crate::parser::safety_annotations::check_method_safety_annotation;
527
528    let kind = entity.get_kind();
529    let is_method = kind == EntityKind::Method || kind == EntityKind::Constructor;
530
531    // Parse safety annotation from comments (uses source file reading fallback)
532    let safety_annotation = check_method_safety_annotation(entity);
533    let has_explicit_safety_annotation = safety_annotation.is_some();
534
535    // Use qualified name for ALL functions (methods AND free functions in namespaces)
536    // This ensures:
537    // 1. Methods get qualified names like "MyClass::method"
538    // 2. Namespaced functions get qualified names like "network::send_message"
539    // 3. External library functions get qualified names like "YAML::detail::node_data::get"
540    // This prevents false matches where unqualified "get" incorrectly matches "rusty::Cell::get"
541    let name = get_qualified_name(entity);
542    let location = extract_location(entity);
543
544    let mut parameters = Vec::new();
545    for child in entity.get_children() {
546        if child.get_kind() == EntityKind::ParmDecl {
547            let mut param = extract_variable(&child);
548
549            // Phase 1: Detect variadic parameter packs
550            // Check if this is a parameter pack by examining the type
551            if let Some(param_type) = child.get_type() {
552                let type_str = type_to_string(&param_type);
553
554                // Check if type contains "..." (e.g., "Args...", "Args &&...", "const T &...")
555                let is_pack = type_str.contains("...") || child.is_variadic();
556
557                if is_pack {
558                    param.is_pack = true;
559
560                    // Extract element type by removing "..." from the type string
561                    let element_type = type_str.trim_end_matches("...").trim().to_string();
562                    param.pack_element_type = Some(element_type.clone());
563
564                    debug_println!("DEBUG PARSE: Found parameter pack '{}' with element type '{}'",
565                        param.name, element_type);
566                }
567            }
568
569            parameters.push(param);
570        }
571    }
572
573    let return_type = entity
574        .get_result_type()
575        .map(|t| type_to_string(&t))
576        .unwrap_or_else(|| "void".to_string());
577
578    let body = extract_function_body(entity);
579
580    // Detect method qualifier and class name
581    let (method_qualifier, class_name) = if is_method {
582        let qualifier = detect_method_qualifier(entity);
583        let class_name = entity.get_semantic_parent()
584            .and_then(|parent| parent.get_name());
585        (Some(qualifier), class_name)
586    } else {
587        (None, None)
588    };
589
590    // Extract template parameters from:
591    // 1. ClassTemplate parent (for template class methods)
592    // 2. FunctionTemplate entity itself (for free template functions)
593    // 3. FunctionTemplate parent (fallback for nested cases)
594    let template_parameters = if is_method {
595        // Check if parent is a ClassTemplate
596        if let Some(parent) = entity.get_semantic_parent() {
597            if parent.get_kind() == EntityKind::ClassTemplate {
598                debug_println!("TEMPLATE: Method in template class, extracting parameters");
599                extract_template_parameters(&parent)
600            } else {
601                Vec::new()
602            }
603        } else {
604            Vec::new()
605        }
606    } else if entity.get_kind() == EntityKind::FunctionTemplate {
607        // Entity IS a FunctionTemplate - extract parameters directly from it
608        debug_println!("TEMPLATE: Free template function (entity is FunctionTemplate), extracting parameters");
609        extract_template_parameters(entity)
610    } else {
611        // For free functions, check if parent is a FunctionTemplate (fallback)
612        if let Some(parent) = entity.get_semantic_parent() {
613            if parent.get_kind() == EntityKind::FunctionTemplate {
614                debug_println!("TEMPLATE: Free template function, extracting parameters from FunctionTemplate parent");
615                extract_template_parameters(&parent)
616            } else {
617                Vec::new()
618            }
619        } else {
620            Vec::new()
621        }
622    };
623
624    Function {
625        name,
626        parameters,
627        return_type,
628        body,
629        location,
630        is_method,
631        method_qualifier,
632        class_name,
633        template_parameters,
634        safety_annotation,
635        has_explicit_safety_annotation,
636    }
637}
638
639// Phase 3: Extract class template information
640pub fn extract_class(entity: &Entity) -> Class {
641    use crate::debug_println;
642    use crate::parser::safety_annotations::{check_class_interface_annotation, parse_entity_safety};
643
644    // Bug #8 fix: Use qualified name for classes to prevent namespace collision
645    // e.g., "yaml::Node" instead of just "Node"
646    let name = get_qualified_name(entity);
647    let location = extract_location(entity);
648    let is_template = entity.get_kind() == EntityKind::ClassTemplate;
649
650    debug_println!("DEBUG PARSE: Extracting class '{}', is_template={}", name, is_template);
651
652    // Extract template parameters from ClassTemplate
653    let template_parameters = if is_template {
654        extract_template_parameters(entity)
655    } else {
656        Vec::new()
657    };
658
659    debug_println!("DEBUG PARSE: Class '{}' has {} template parameters: {:?}",
660        name, template_parameters.len(), template_parameters);
661
662    // Check for @interface annotation
663    let is_interface = check_class_interface_annotation(entity);
664    if is_interface {
665        debug_println!("DEBUG PARSE: Class '{}' is marked as @interface", name);
666    }
667
668    // Check for @safe/@unsafe annotation on the class
669    let safety_annotation = parse_entity_safety(entity);
670
671    let mut members = Vec::new();
672    let mut methods = Vec::new();
673    let mut base_classes = Vec::new();
674    let mut has_destructor = false;  // RAII Phase 2: Track destructors
675    let mut has_virtual_destructor = false;
676    let mut destructor_is_defaulted = false;
677    let mut has_non_virtual_methods = false;
678    let mut all_methods_pure_virtual = true;  // Start true, set false if we find non-pure method
679    let mut has_any_method = false;  // Track if there are any methods to check
680    // Copy semantics tracking
681    let mut has_copy_constructor = false;
682    let mut has_copy_assignment = false;
683    let mut copy_constructor_deleted = false;
684    let mut copy_assignment_deleted = false;
685
686    // LibClang's get_children() flattens the hierarchy and returns class members directly
687    // (FieldDecl, Method, etc.) rather than going through CXXRecordDecl
688    for child in entity.get_children() {
689        debug_println!("DEBUG PARSE: ClassTemplate child kind: {:?}", child.get_kind());
690        match child.get_kind() {
691            EntityKind::FieldDecl => {
692                // Member field
693                let mut member = extract_variable(&child);
694
695                // Phase 3: Check if member type contains pack expansion
696                if let Some(field_type) = child.get_type() {
697                    let type_str = type_to_string(&field_type);
698                    if type_str.contains("...") {
699                        debug_println!("DEBUG PARSE: Found member field with pack expansion: '{}' of type '{}'",
700                            member.name, type_str);
701                        member.is_pack = true;
702                        member.pack_element_type = Some(type_str.clone());
703                    }
704                }
705
706                members.push(member);
707            }
708            EntityKind::Destructor => {
709                // RAII Phase 2: Mark class as having a destructor
710                has_destructor = true;
711                debug_println!("DEBUG PARSE: Class '{}' has user-defined destructor", name);
712
713                // Check if destructor is virtual
714                if child.is_virtual_method() {
715                    has_virtual_destructor = true;
716                    debug_println!("DEBUG PARSE: Class '{}' has virtual destructor", name);
717                }
718
719                // Check if destructor is defaulted (= default)
720                if child.is_defaulted() {
721                    destructor_is_defaulted = true;
722                    debug_println!("DEBUG PARSE: Class '{}' has defaulted destructor", name);
723                }
724
725                let method = extract_function(&child);
726                methods.push(method);
727            }
728            EntityKind::Method | EntityKind::Constructor => {
729                // Member method
730                let method = extract_function(&child);
731                let is_deleted = is_deleted_or_defaulted_method(&child);
732
733                // Check for copy constructor
734                if child.get_kind() == EntityKind::Constructor {
735                    if child.is_copy_constructor() {
736                        has_copy_constructor = true;
737                        if is_deleted {
738                            copy_constructor_deleted = true;
739                            debug_println!("DEBUG PARSE: Class '{}' has deleted copy constructor", name);
740                        } else {
741                            debug_println!("DEBUG PARSE: Class '{}' has copy constructor", name);
742                        }
743                    }
744                }
745
746                // Skip constructors for pure virtual check
747                if child.get_kind() == EntityKind::Method {
748                    has_any_method = true;
749
750                    // Check for copy assignment operator: operator=(const ClassName&)
751                    if let Some(method_name) = child.get_name() {
752                        if method_name == "operator=" {
753                            // Check if parameter is const reference to same class type
754                            let children = child.get_children();
755                            for param_child in &children {
756                                if param_child.get_kind() == EntityKind::ParmDecl {
757                                    if let Some(param_type) = param_child.get_type() {
758                                        let type_str = type_to_string(&param_type);
759                                        // Copy assignment takes const ClassName& or ClassName const&
760                                        // Get the unqualified class name for comparison
761                                        let simple_name = name.split("::").last().unwrap_or(&name);
762                                        if type_str.contains(simple_name) &&
763                                           type_str.contains("const") &&
764                                           type_str.contains("&") &&
765                                           !type_str.contains("&&") {
766                                            has_copy_assignment = true;
767                                            if is_deleted {
768                                                copy_assignment_deleted = true;
769                                                debug_println!("DEBUG PARSE: Class '{}' has deleted copy assignment", name);
770                                            } else {
771                                                debug_println!("DEBUG PARSE: Class '{}' has copy assignment", name);
772                                            }
773                                        }
774                                    }
775                                    break;  // Only check first parameter
776                                }
777                            }
778                        }
779                    }
780
781                    // Check if method is virtual, deleted, or defaulted
782                    let is_virtual = child.is_virtual_method();
783                    let is_pure_virtual = child.is_pure_virtual_method();
784
785                    // Deleted/defaulted methods (= delete, = default) don't count as
786                    // non-virtual methods for @interface validation. They are special
787                    // member functions, not regular callable methods.
788                    if !is_virtual && !is_deleted {
789                        has_non_virtual_methods = true;
790                        debug_println!("DEBUG PARSE: Class '{}' has non-virtual method: {:?}", name, child.get_name());
791                    }
792
793                    // Deleted/defaulted methods also don't count for pure virtual check
794                    if !is_pure_virtual && !is_deleted {
795                        all_methods_pure_virtual = false;
796                        debug_println!("DEBUG PARSE: Class '{}' has non-pure-virtual method: {:?}", name, child.get_name());
797                    }
798                }
799
800                methods.push(method);
801            }
802            EntityKind::FunctionTemplate => {
803                // Template method
804                if child.is_definition() {
805                    let method = extract_function(&child);
806                    methods.push(method);
807                    // Template methods cannot be pure virtual
808                    has_any_method = true;
809                    all_methods_pure_virtual = false;
810                    has_non_virtual_methods = true;
811                }
812            }
813            EntityKind::BaseSpecifier => {
814                // Base class
815                if let Some(base_type) = child.get_type() {
816                    let base_name = type_to_string(&base_type);
817                    debug_println!("DEBUG PARSE: Found base class: '{}'", base_name);
818                    base_classes.push(base_name);
819                }
820            }
821            _ => {}
822        }
823    }
824
825    // If no methods at all, all_methods_pure_virtual should be true (vacuously true for interfaces)
826    if !has_any_method {
827        all_methods_pure_virtual = true;
828    }
829
830    debug_println!("DEBUG PARSE: Class '{}' has {} members, {} methods, {} base classes, has_destructor={}, is_interface={}, has_virtual_destructor={}, destructor_is_defaulted={}, all_methods_pure_virtual={}, has_non_virtual_methods={}, has_copy_constructor={} (deleted={}), has_copy_assignment={} (deleted={})",
831        name, members.len(), methods.len(), base_classes.len(), has_destructor, is_interface, has_virtual_destructor, destructor_is_defaulted, all_methods_pure_virtual, has_non_virtual_methods,
832        has_copy_constructor, copy_constructor_deleted, has_copy_assignment, copy_assignment_deleted);
833
834    Class {
835        name,
836        template_parameters,
837        is_template,
838        members,
839        methods,
840        base_classes,
841        location,
842        has_destructor,  // RAII Phase 2
843        // Inheritance safety fields
844        is_interface,
845        has_virtual_destructor,
846        destructor_is_defaulted,
847        all_methods_pure_virtual,
848        has_non_virtual_methods,
849        safety_annotation,
850        // Copy semantics
851        has_copy_constructor,
852        has_copy_assignment,
853        copy_constructor_deleted,
854        copy_assignment_deleted,
855    }
856}
857
858/// Detect the qualifier of a method (const, non-const, or rvalue-ref)
859fn detect_method_qualifier(entity: &Entity) -> MethodQualifier {
860    // Check if this is a const method
861    let is_const = entity.is_const_method();
862
863    // Check for && qualifier (rvalue reference qualifier)
864    // LibClang doesn't expose this directly, so we check the function type
865    let has_rvalue_ref_qualifier = if let Some(func_type) = entity.get_type() {
866        // Check the display name for && qualifier
867        let type_str = type_to_string(&func_type);
868        debug_println!("DEBUG METHOD: type_str = {}", type_str);
869
870        // The type string may contain "&&" for rvalue ref qualifier
871        // Example: "void () &&" or "void (int) &&"
872        type_str.contains(" &&") || type_str.ends_with("&&")
873    } else {
874        false
875    };
876
877    debug_println!("DEBUG METHOD: is_const={}, has_rvalue_ref={}", is_const, has_rvalue_ref_qualifier);
878
879    // Determine the qualifier
880    if has_rvalue_ref_qualifier {
881        MethodQualifier::RvalueRef
882    } else if is_const {
883        MethodQualifier::Const
884    } else {
885        MethodQualifier::NonConst
886    }
887}
888
889pub fn extract_variable(entity: &Entity) -> Variable {
890    let name = entity.get_name().unwrap_or_else(|| "anonymous".to_string());
891    let location = extract_location(entity);
892    
893    let type_info = entity.get_type().unwrap();
894    let type_name = type_to_string(&type_info);
895    
896    let is_reference = matches!(type_info.get_kind(), TypeKind::LValueReference | TypeKind::RValueReference);
897    let is_pointer = matches!(type_info.get_kind(), TypeKind::Pointer);
898    
899    // For references, check if the pointee type is const
900    let is_const = if is_reference {
901        if let Some(pointee) = type_info.get_pointee_type() {
902            pointee.is_const_qualified()
903        } else {
904            type_info.is_const_qualified()
905        }
906    } else {
907        type_info.is_const_qualified()
908    };
909    
910    let is_unique_ptr = type_name.contains("unique_ptr");
911    let is_shared_ptr = type_name.contains("shared_ptr");
912
913    // Check if this is a static variable
914    // In clang, static variables have StorageClass::Static
915    let is_static = entity.get_storage_class() == Some(clang::StorageClass::Static);
916
917    // Check if this is a mutable field (C++ mutable keyword)
918    // We need to read the source code to check for the 'mutable' keyword
919    // because libclang doesn't expose mutable as a storage class
920    let is_mutable = check_for_mutable_keyword(entity);
921    debug_println!("DEBUG MUTABLE: Field '{}' is_mutable = {}", name, is_mutable);
922
923    Variable {
924        name,
925        type_name,
926        is_reference,
927        is_pointer,
928        is_const,
929        is_unique_ptr,
930        is_shared_ptr,
931        is_static,
932        is_mutable,
933        location,
934        is_pack: false,              // Will be set properly for function parameters
935        pack_element_type: None,     // Will be set properly for function parameters
936    }
937}
938
939fn extract_function_body(entity: &Entity) -> Vec<Statement> {
940    let mut statements = Vec::new();
941    
942    for child in entity.get_children() {
943        if child.get_kind() == EntityKind::CompoundStmt {
944            statements.extend(extract_compound_statement(&child));
945        }
946    }
947    
948    statements
949}
950
951/// Helper function to extract function name from a CallExpr
952/// Returns None if the function name cannot be determined
953fn extract_function_name(call_expr: &Entity) -> Option<String> {
954    debug_println!("DEBUG: Extracting function name from CallExpr");
955
956    // Try to get name from the first child (usually the callee)
957    for child in call_expr.get_children() {
958        // Check DeclRefExpr or UnexposedExpr for function name
959        if matches!(child.get_kind(), EntityKind::DeclRefExpr | EntityKind::UnexposedExpr) {
960            if let Some(ref_entity) = child.get_reference() {
961                if let Some(name) = ref_entity.get_name() {
962                    debug_println!("DEBUG: Found function name '{}' from reference", name);
963                    return Some(name);
964                }
965            }
966            if let Some(name) = child.get_name() {
967                debug_println!("DEBUG: Found function name '{}' from child name", name);
968                return Some(name);
969            }
970        }
971    }
972
973    None
974}
975
976fn extract_compound_statement(entity: &Entity) -> Vec<Statement> {
977    let mut statements = Vec::new();
978
979    for child in entity.get_children() {
980        debug_println!("DEBUG STMT: Compound child kind: {:?}", child.get_kind());
981        match child.get_kind() {
982            EntityKind::DeclStmt => {
983                for decl_child in child.get_children() {
984                    if decl_child.get_kind() == EntityKind::VarDecl {
985                        let var = extract_variable(&decl_child);
986                        
987                        // Always add the variable declaration first
988                        statements.push(Statement::VariableDecl(var.clone()));
989                        
990                        // Check if this variable has an initializer
991                        for init_child in decl_child.get_children() {
992                            if let Some(expr) = extract_expression(&init_child) {
993                                
994                                // Check if this is a reference binding
995                                if var.is_reference {
996                                    statements.push(Statement::ReferenceBinding {
997                                        name: var.name.clone(),
998                                        target: expr,
999                                        is_mutable: !var.is_const,
1000                                        location: extract_location(&decl_child),
1001                                    });
1002                                } else {
1003                                    // Regular assignment/initialization
1004                                    statements.push(Statement::Assignment {
1005                                        lhs: Expression::Variable(var.name.clone()),
1006                                        rhs: expr,
1007                                        location: extract_location(&decl_child),
1008                                    });
1009                                }
1010                                break;
1011                            }
1012                        }
1013                    }
1014                }
1015            }
1016            EntityKind::BinaryOperator => {
1017                // Handle assignments
1018                let children: Vec<Entity> = child.get_children().into_iter().collect();
1019                debug_println!("DEBUG STMT: BinaryOperator has {} children", children.len());
1020                if children.len() == 2 {
1021                    debug_println!("DEBUG STMT: BinaryOperator child[0] kind: {:?}", children[0].get_kind());
1022                    debug_println!("DEBUG STMT: BinaryOperator child[1] kind: {:?}", children[1].get_kind());
1023                    let lhs_expr = extract_expression(&children[0]);
1024                    let rhs_expr = extract_expression(&children[1]);
1025                    debug_println!("DEBUG STMT: BinaryOperator LHS: {:?}", lhs_expr);
1026                    debug_println!("DEBUG STMT: BinaryOperator RHS: {:?}", rhs_expr);
1027                    if let (Some(lhs), Some(rhs)) = (lhs_expr, rhs_expr) {
1028                        debug_println!("DEBUG STMT: Creating Assignment statement");
1029                        statements.push(Statement::Assignment {
1030                            lhs,  // Now supports dereference: *ptr = value
1031                            rhs,
1032                            location: extract_location(&child),
1033                        });
1034                    } else {
1035                        debug_println!("DEBUG STMT: Failed to extract expressions from BinaryOperator");
1036                    }
1037                }
1038            }
1039            EntityKind::CallExpr => {
1040                let children: Vec<Entity> = child.get_children().into_iter().collect();
1041                let mut name = "unknown".to_string();
1042                let mut args = Vec::new();
1043                
1044                // Check if this might be a variable declaration disguised as a CallExpr
1045                // This happens with constructs like "struct timeval now;" or "ClassName obj;"
1046                let mut is_likely_var_decl = false;
1047                
1048                // Debug: Log all CallExprs
1049                debug_println!("DEBUG AST: Found CallExpr with {} children", children.len());
1050                
1051                // First check if the CallExpr itself has a reference
1052                if let Some(ref_entity) = child.get_reference() {
1053                    debug_println!("DEBUG AST: CallExpr references entity kind: {:?}, name: {:?}", 
1054                        ref_entity.get_kind(), ref_entity.get_name());
1055                    
1056                    // Check if it references a type (struct/class/typedef)
1057                    if ref_entity.get_kind() == EntityKind::StructDecl || 
1058                       ref_entity.get_kind() == EntityKind::ClassDecl ||
1059                       ref_entity.get_kind() == EntityKind::TypedefDecl ||
1060                       ref_entity.get_kind() == EntityKind::TypeAliasDecl {
1061                        // This is likely a variable declaration, not a function call
1062                        debug_println!("DEBUG AST: CallExpr appears to be a variable declaration of type {:?}", 
1063                            ref_entity.get_name());
1064                        is_likely_var_decl = true;
1065                    }
1066                    
1067                    if let Some(_n) = ref_entity.get_name() {
1068                        // Build qualified name for ALL functions (methods AND free functions)
1069                        // This ensures:
1070                        // 1. Methods get qualified names like "MyClass::method"
1071                        // 2. Namespaced functions get qualified names like "mylib::dangerous_op"
1072                        // This prevents false matches between same-named functions in different namespaces
1073                        name = get_qualified_name(&ref_entity);
1074                    }
1075                }
1076                
1077                // If this looks like a variable declaration, skip it
1078                if is_likely_var_decl && children.is_empty() {
1079                    debug_println!("DEBUG AST: Skipping variable declaration disguised as CallExpr: {}", name);
1080                    continue;
1081                }
1082                
1083                // Try to extract the function name from children
1084                // CRITICAL: EXCLUDE entities that reference variables/parameters
1085                // (which caused the "rhs"/"schema"/"vv" bugs where args were mistaken for function names)
1086                for (idx, c) in children.iter().enumerate() {
1087                    debug_println!("DEBUG AST: CallExpr child[{}] kind: {:?}, name: {:?}, display_name: {:?}, reference: {:?}",
1088                        idx, c.get_kind(), c.get_name(), c.get_display_name(),
1089                        c.get_reference().map(|r| (r.get_kind(), r.get_name())));
1090
1091                    if c.get_kind() == EntityKind::UnexposedExpr || c.get_kind() == EntityKind::DeclRefExpr {
1092                        // Check if this entity references a variable/parameter - if so, skip it
1093                        if let Some(ref_entity) = c.get_reference() {
1094                            let ref_kind = ref_entity.get_kind();
1095                            // EXCLUDE variables and parameters - these are arguments, not function names
1096                            if ref_kind == EntityKind::VarDecl || ref_kind == EntityKind::ParmDecl {
1097                                debug_println!("DEBUG AST: Skipping variable/parameter reference: {:?}", ref_kind);
1098                                continue;
1099                            }
1100                            // This is a function reference - use qualified name
1101                            if name == "unknown" {
1102                                let qualified = get_qualified_name(&ref_entity);
1103                                debug_println!("DEBUG AST: Got qualified name from child reference: {}", qualified);
1104                                name = qualified;
1105                            }
1106                        } else {
1107                            // No reference (template-dependent) - use unqualified name as fallback
1108                            if let Some(n) = c.get_name() {
1109                                if name == "unknown" {
1110                                    debug_println!("DEBUG AST: Got name from child (template-dependent): {}", n);
1111                                    name = n;
1112                                }
1113                            }
1114                        }
1115                    }
1116                }
1117                
1118                // Check if this is a type name being used as a constructor/declaration
1119                // Common pattern: TypeName varname; is parsed as CallExpr
1120                if children.len() == 1 && name != "unknown" {
1121                    // Check if the name matches known type patterns
1122                    if name.ends_with("val") || name.ends_with("spec") || 
1123                       name.starts_with("struct") || name.starts_with("class") {
1124                        debug_println!("DEBUG AST: Likely variable declaration based on name pattern: {}", name);
1125                        is_likely_var_decl = true;
1126                    }
1127                }
1128                
1129                // If this looks like a variable declaration, skip it
1130                if is_likely_var_decl {
1131                    debug_println!("DEBUG AST: Skipping variable declaration disguised as CallExpr: {}", name);
1132                    continue;
1133                }
1134                
1135                // Two-pass approach: identify name-providing child, then extract args
1136                let mut name_providing_child_idx: Option<usize> = None;
1137
1138                // Pass 1: If name still unknown, find it; otherwise identify which child has it
1139                if name == "unknown" {
1140                    for (i, c) in children.iter().enumerate() {
1141                        debug_println!("DEBUG AST: Child {}: kind={:?}, name={:?}", i, c.get_kind(), c.get_name());
1142                        match c.get_kind() {
1143                            EntityKind::MemberRefExpr => {
1144                                debug_println!("DEBUG AST: Found MemberRefExpr!");
1145                                if let Some(ref_entity) = c.get_reference() {
1146                                    debug_println!("DEBUG AST: MemberRefExpr has reference: kind={:?}, name={:?}",
1147                                        ref_entity.get_kind(), ref_entity.get_name());
1148                                    if let Some(_n) = ref_entity.get_name() {
1149                                        // Use qualified name for ALL function calls
1150                                        name = get_qualified_name(&ref_entity);
1151                                        name_providing_child_idx = Some(i);
1152                                        break;
1153                                    }
1154                                } else {
1155                                    debug_println!("DEBUG AST: MemberRefExpr has NO reference!");
1156                                }
1157                            }
1158                            EntityKind::DeclRefExpr | EntityKind::UnexposedExpr => {
1159                                // CRITICAL FIX: EXCLUDE variables/parameters
1160                                // (which caused the "rhs"/"schema"/"vv" bugs)
1161                                if let Some(ref_entity) = c.get_reference() {
1162                                    let ref_kind = ref_entity.get_kind();
1163                                    if ref_kind == EntityKind::VarDecl || ref_kind == EntityKind::ParmDecl {
1164                                        continue; // Skip variables/parameters
1165                                    }
1166                                    // Use qualified name for function calls
1167                                    let qualified = get_qualified_name(&ref_entity);
1168                                    name = qualified;
1169                                    name_providing_child_idx = Some(i);
1170                                    break;
1171                                } else if let Some(n) = c.get_name() {
1172                                    // No reference (template-dependent) - use unqualified name
1173                                    name = n;
1174                                    name_providing_child_idx = Some(i);
1175                                    break;
1176                                }
1177                            }
1178                            _ => {}
1179                        }
1180                    }
1181                } else {
1182                    // Name already known, find which child provides it
1183                    debug_println!("DEBUG AST: Name already known: '{}', searching {} children", name, children.len());
1184                    for (i, c) in children.iter().enumerate() {
1185                        debug_println!("DEBUG AST: Child {}: kind={:?}, name={:?}", i, c.get_kind(), c.get_name());
1186                        match c.get_kind() {
1187                            EntityKind::MemberRefExpr => {
1188                                // For .method() calls, MemberRefExpr contains the method name
1189                                debug_println!("DEBUG AST: Exploring MemberRefExpr for receiver object:");
1190                                debug_println!("  - name: {:?}", c.get_name());
1191                                debug_println!("  - display_name: {:?}", c.get_display_name());
1192                                debug_println!("  - num children: {}", c.get_children().len());
1193
1194                                // Check if MemberRefExpr has children
1195                                for (child_idx, member_child) in c.get_children().iter().enumerate() {
1196                                    debug_println!("    - MemberRefExpr child {}: kind={:?}, name={:?}",
1197                                        child_idx, member_child.get_kind(), member_child.get_name());
1198                                }
1199
1200                                // Check semantic parent
1201                                if let Some(semantic_parent) = c.get_semantic_parent() {
1202                                    debug_println!("  - semantic_parent: kind={:?}, name={:?}",
1203                                        semantic_parent.get_kind(), semantic_parent.get_name());
1204                                }
1205
1206                                // Check lexical parent
1207                                if let Some(lexical_parent) = c.get_lexical_parent() {
1208                                    debug_println!("  - lexical_parent: kind={:?}, name={:?}",
1209                                        lexical_parent.get_kind(), lexical_parent.get_name());
1210                                }
1211
1212                                if let Some(child_name) = c.get_name() {
1213                                    debug_println!("DEBUG AST: Checking if '{}' matches name '{}'", child_name, name);
1214                                    if name.ends_with(&child_name) || name == child_name {
1215                                        debug_println!("DEBUG AST: Match found! Setting name_providing_child_idx = {}", i);
1216                                        name_providing_child_idx = Some(i);
1217                                        break;
1218                                    }
1219                                }
1220                            }
1221                            EntityKind::DeclRefExpr | EntityKind::UnexposedExpr => {
1222                                if let Some(child_name) = c.get_name() {
1223                                    debug_println!("DEBUG AST: Checking if '{}' matches name '{}'", child_name, name);
1224                                    if name.ends_with(&child_name) || name == child_name {
1225                                        debug_println!("DEBUG AST: Match found! Setting name_providing_child_idx = {}", i);
1226                                        name_providing_child_idx = Some(i);
1227                                        break;
1228                                    }
1229                                }
1230                            }
1231                            _ => {}
1232                        }
1233                    }
1234                    debug_println!("DEBUG AST: name_providing_child_idx = {:?}", name_providing_child_idx);
1235                }
1236
1237                // Pass 2: Extract arguments, skipping name-providing child
1238                for (i, c) in children.into_iter().enumerate() {
1239                    if Some(i) == name_providing_child_idx {
1240                        // For MemberRefExpr, extract the receiver from its children
1241                        if c.get_kind() == EntityKind::MemberRefExpr {
1242                            debug_println!("DEBUG AST: Extracting receiver from MemberRefExpr");
1243                            let member_children: Vec<Entity> = c.get_children().into_iter().collect();
1244                            if !member_children.is_empty() {
1245                                // Has children - extract receiver from first child
1246                                if let Some(receiver_expr) = extract_expression(&member_children[0]) {
1247                                    // Check if receiver type is a pointer (means -> was used)
1248                                    // ptr->method() is semantically (*ptr).method(), so wrap in Dereference
1249                                    // EXCEPT for safe smart pointers whose operator-> is safe
1250                                    let is_arrow = member_children[0].get_type()
1251                                        .map(|t| matches!(t.get_kind(), TypeKind::Pointer))
1252                                        .unwrap_or(false);
1253
1254                                    // Check if this is an overloaded operator-> (smart pointer)
1255                                    // Raw pointers use built-in ->, smart pointers call operator->
1256                                    let has_overloaded_arrow = if is_arrow {
1257                                        has_overloaded_arrow_operator(&member_children[0])
1258                                    } else {
1259                                        false
1260                                    };
1261
1262                                    if is_arrow && !has_overloaded_arrow {
1263                                        debug_println!("DEBUG AST: Raw pointer arrow method call: (*{:?})", receiver_expr);
1264                                        args.push(Expression::Dereference(Box::new(receiver_expr)));
1265                                    } else {
1266                                        debug_println!("DEBUG AST: Dot/smart pointer method call: {:?}", receiver_expr);
1267                                        args.push(receiver_expr);
1268                                    }
1269                                }
1270                            } else {
1271                                // No children - the receiver is a simple variable/parameter
1272                                // Extract it from the MemberRefExpr's name or display name
1273                                if let Some(member_name) = c.get_name() {
1274                                    // The name might be like "m" for m.content_size()
1275                                    // But we need to be careful - the name might be the method name
1276                                    // Check if this is different from our extracted function name
1277                                    if member_name != name && !name.ends_with(&member_name) {
1278                                        debug_println!("DEBUG AST: Found receiver from MemberRefExpr name: {}", member_name);
1279                                        args.push(Expression::Variable(member_name));
1280                                    }
1281                                } else if let Some(display) = c.get_display_name() {
1282                                    // Try display name as fallback
1283                                    if display != name && !name.ends_with(&display) && !display.is_empty() {
1284                                        debug_println!("DEBUG AST: Found receiver from MemberRefExpr display: {}", display);
1285                                        args.push(Expression::Variable(display));
1286                                    }
1287                                }
1288                            }
1289                        }
1290                        continue;  // Skip the MemberRefExpr itself
1291                    }
1292
1293                    // Phase 2: Check if this argument is a PackExpansionExpr
1294                    if c.get_kind() == EntityKind::PackExpansionExpr {
1295                        debug_println!("DEBUG STMT: Found PackExpansionExpr as function argument");
1296
1297                        let mut pack_name = String::new();
1298                        let mut operation = "use".to_string();
1299
1300                        // Look for the pack name and operation type
1301                        for pack_child in c.get_children() {
1302                            // Check if it's a CallExpr (could be std::forward or std::move)
1303                            if pack_child.get_kind() == EntityKind::CallExpr {
1304                                if let Some(callee_name) = extract_function_name(&pack_child) {
1305                                    debug_println!("DEBUG STMT: PackExpansion contains call to: {}", callee_name);
1306                                    if is_forward_function(&callee_name) {
1307                                        operation = "forward".to_string();
1308                                    } else if is_move_function(&callee_name) {
1309                                        operation = "move".to_string();
1310                                    }
1311                                }
1312
1313                                // Find pack name inside the call
1314                                // Skip the first child (function name) and look for parameter references
1315                                debug_println!("DEBUG STMT: Searching for pack name in CallExpr children (count: {})",
1316                                    pack_child.get_children().len());
1317                                for call_child in pack_child.get_children() {
1318                                    debug_println!("DEBUG STMT: CallExpr child kind: {:?}", call_child.get_kind());
1319                                    if call_child.get_kind() == EntityKind::DeclRefExpr {
1320                                        if let Some(ref_entity) = call_child.get_reference() {
1321                                            debug_println!("DEBUG STMT: DeclRefExpr references entity kind: {:?}", ref_entity.get_kind());
1322                                            // Only accept if it references a parameter (ParmDecl), not a function
1323                                            if ref_entity.get_kind() == EntityKind::ParmDecl {
1324                                                if let Some(name) = ref_entity.get_name() {
1325                                                    debug_println!("DEBUG STMT: Found pack name '{}' inside CallExpr", name);
1326                                                    pack_name = name;
1327                                                    break;
1328                                                }
1329                                            }
1330                                        }
1331                                    }
1332                                }
1333                            }
1334                            // Direct DeclRefExpr (pack used without forward/move)
1335                            else if pack_child.get_kind() == EntityKind::DeclRefExpr {
1336                                debug_println!("DEBUG STMT: Found direct DeclRefExpr in PackExpansionExpr");
1337                                if let Some(ref_entity) = pack_child.get_reference() {
1338                                    if let Some(name) = ref_entity.get_name() {
1339                                        debug_println!("DEBUG STMT: Pack name from direct DeclRefExpr: '{}'", name);
1340                                        pack_name = name;
1341                                    }
1342                                }
1343                            }
1344                        }
1345
1346                        if !pack_name.is_empty() {
1347                            debug_println!("DEBUG STMT: Pack expansion detected: pack='{}', operation='{}'",
1348                                pack_name, operation);
1349                            statements.push(Statement::PackExpansion {
1350                                pack_name,
1351                                operation,
1352                                location: extract_location(&c),
1353                            });
1354                        }
1355                    }
1356                    // Regular argument extraction
1357                    else if let Some(expr) = extract_expression(&c) {
1358                        args.push(expr);
1359                    }
1360                }
1361                
1362                debug_println!("DEBUG STMT: Creating FunctionCall statement: name='{}', args={:?}", name, args);
1363                statements.push(Statement::FunctionCall {
1364                    name,
1365                    args,
1366                    location: extract_location(&child),
1367                });
1368            }
1369            EntityKind::ReturnStmt => {
1370                // Extract the return value expression
1371                let return_expr = child.get_children()
1372                    .into_iter()
1373                    .find_map(|c| extract_expression(&c));
1374                statements.push(Statement::Return(return_expr));
1375            }
1376            EntityKind::CompoundStmt => {
1377                // Regular nested block scope - add scope markers
1378                statements.push(Statement::EnterScope);
1379
1380                // Check if this block is preceded by @unsafe comment
1381                let is_unsafe = check_for_unsafe_annotation(&child);
1382                if is_unsafe {
1383                    debug_println!("DEBUG UNSAFE: Found @unsafe block");
1384                    statements.push(Statement::EnterUnsafe);
1385                }
1386
1387                statements.extend(extract_compound_statement(&child));
1388
1389                if is_unsafe {
1390                    statements.push(Statement::ExitUnsafe);
1391                }
1392
1393                statements.push(Statement::ExitScope);
1394            }
1395            EntityKind::ForStmt | EntityKind::WhileStmt | EntityKind::DoStmt => {
1396                // Loop detected - add loop markers
1397                statements.push(Statement::EnterLoop);
1398                // Extract loop body (usually a compound statement)
1399                for loop_child in child.get_children() {
1400                    if loop_child.get_kind() == EntityKind::CompoundStmt {
1401                        statements.extend(extract_compound_statement(&loop_child));
1402                    }
1403                }
1404                statements.push(Statement::ExitLoop);
1405            }
1406            EntityKind::IfStmt => {
1407                // Extract if statement
1408                let children: Vec<Entity> = child.get_children().into_iter().collect();
1409                let mut condition = Expression::Literal("true".to_string());
1410                let mut then_branch = Vec::new();
1411                let mut else_branch = None;
1412                
1413                // Parse the if statement structure
1414                let mut i = 0;
1415                while i < children.len() {
1416                    let child_kind = children[i].get_kind();
1417                    
1418                    if child_kind == EntityKind::UnexposedExpr || child_kind == EntityKind::BinaryOperator {
1419                        // This is likely the condition
1420                        if let Some(expr) = extract_expression(&children[i]) {
1421                            condition = expr;
1422                        }
1423                    } else if child_kind == EntityKind::CompoundStmt {
1424                        // This is a branch
1425                        if then_branch.is_empty() {
1426                            then_branch = extract_compound_statement(&children[i]);
1427                        } else {
1428                            else_branch = Some(extract_compound_statement(&children[i]));
1429                        }
1430                    }
1431                    i += 1;
1432                }
1433                
1434                statements.push(Statement::If {
1435                    condition,
1436                    then_branch,
1437                    else_branch,
1438                    location: extract_location(&child),
1439                });
1440            }
1441            EntityKind::UnaryOperator => {
1442                // Handle standalone dereference operations
1443                if let Some(expr) = extract_expression(&child) {
1444                    // Only add as statement if it's a dereference or address-of
1445                    match &expr {
1446                        Expression::Dereference(_) | Expression::AddressOf(_) => {
1447                            statements.push(Statement::ExpressionStatement {
1448                                expr,
1449                                location: extract_location(&child),
1450                            });
1451                        }
1452                        _ => {} // Ignore other unary operators for now
1453                    }
1454                }
1455            }
1456            EntityKind::UnexposedExpr => {
1457                // UnexposedExpr can contain function calls or other expressions
1458                // Also check if this contains a PackExpansionExpr (fold expression)
1459
1460                // First check for pack expansions in children
1461                let has_pack_expansion = child.get_children().iter()
1462                    .any(|c| c.get_kind() == EntityKind::PackExpansionExpr);
1463
1464                if has_pack_expansion {
1465                    debug_println!("DEBUG STMT: UnexposedExpr contains PackExpansionExpr (fold expression)");
1466                    // Process PackExpansionExpr children
1467                    for ue_child in child.get_children() {
1468                        if ue_child.get_kind() == EntityKind::PackExpansionExpr {
1469                            // Recursively process the pack expansion
1470                            let pack_stmts = extract_compound_statement(&ue_child);
1471                            statements.extend(pack_stmts);
1472                        }
1473                    }
1474                } else {
1475                    // Regular UnexposedExpr handling
1476                    if let Some(expr) = extract_expression(&child) {
1477                        match expr {
1478                            Expression::FunctionCall { name, args } => {
1479                                statements.push(Statement::FunctionCall {
1480                                    name,
1481                                    args,
1482                                    location: extract_location(&child),
1483                                });
1484                            }
1485                            _ => {
1486                                // Other expression types - add as expression statement
1487                                statements.push(Statement::ExpressionStatement {
1488                                    expr,
1489                                    location: extract_location(&child),
1490                                });
1491                            }
1492                        }
1493                    }
1494                }
1495            }
1496            _ => {}
1497        }
1498    }
1499
1500    statements
1501}
1502
1503fn extract_expression(entity: &Entity) -> Option<Expression> {
1504    match entity.get_kind() {
1505        EntityKind::DeclRefExpr => {
1506            // Check what kind of entity this DeclRefExpr references
1507            if let Some(ref_entity) = entity.get_reference() {
1508                if ref_entity.get_kind() == EntityKind::FieldDecl {
1509                    // This is a member field access - convert to this.field
1510                    if let Some(field_name) = entity.get_name() {
1511                        debug_println!("DEBUG: DeclRefExpr to FieldDecl '{}' - converting to this.{}", field_name, field_name);
1512                        return Some(Expression::MemberAccess {
1513                            object: Box::new(Expression::Variable("this".to_string())),
1514                            field: field_name,
1515                        });
1516                    }
1517                }
1518                // Check if this references a method (member function)
1519                if ref_entity.get_kind() == EntityKind::Method || ref_entity.get_kind() == EntityKind::FunctionDecl {
1520                    // This is a function/method reference - include class qualifier if available
1521                    if let Some(func_name) = entity.get_name() {
1522                        // Try to get the class name from semantic parent
1523                        if let Some(parent) = ref_entity.get_semantic_parent() {
1524                            if matches!(parent.get_kind(), EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate) {
1525                                if let Some(class_name) = parent.get_name() {
1526                                    // Return qualified name: ClassName::method
1527                                    return Some(Expression::Variable(format!("{}::{}", class_name, func_name)));
1528                                }
1529                            }
1530                        }
1531                        // No class parent, return just the function name
1532                        return Some(Expression::Variable(func_name));
1533                    }
1534                }
1535            }
1536            // Regular variable reference
1537            entity.get_name().map(Expression::Variable)
1538        }
1539        EntityKind::ThisExpr => {
1540            // The 'this' pointer in C++ methods
1541            Some(Expression::Variable("this".to_string()))
1542        }
1543        EntityKind::CallExpr => {
1544            // Extract function call as expression
1545            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1546            let mut name = "unknown".to_string();
1547            let mut args = Vec::new();
1548            
1549            // Check if this might be a variable declaration disguised as a CallExpr
1550            // This happens with constructs like "struct timeval now;" or "ClassName obj;"
1551            // The pattern is: CallExpr with 0 children that references a type name
1552            
1553            // First check if the CallExpr itself has a reference
1554            let mut method_name_from_callexpr = false;
1555            if let Some(ref_entity) = entity.get_reference() {
1556                debug_println!("DEBUG AST: CallExpr itself references: {:?}", ref_entity.get_name());
1557
1558                // Check if it references a type (struct/class/typedef)
1559                // BUT: A CallExpr with 0 children is likely a constructor/declaration
1560                if children.is_empty() {
1561                    if let Some(n) = ref_entity.get_name() {
1562                        name = n;
1563                    }
1564                    debug_println!("DEBUG AST: CallExpr with 0 children referencing '{}' - likely a variable declaration", name);
1565                    return None;  // Not a function call, it's a variable declaration
1566                }
1567
1568                // Build qualified name for all functions to avoid namespace collisions
1569                // This ensures ns1::func and ns2::func are distinguished
1570                if ref_entity.get_kind() == EntityKind::Method
1571                    || ref_entity.get_kind() == EntityKind::Constructor
1572                    || ref_entity.get_kind() == EntityKind::FunctionDecl
1573                    || ref_entity.get_kind() == EntityKind::FunctionTemplate {
1574                    name = get_qualified_name(&ref_entity);
1575                    if ref_entity.get_kind() == EntityKind::Method || ref_entity.get_kind() == EntityKind::Constructor {
1576                        method_name_from_callexpr = true;
1577                    }
1578                    debug_println!("DEBUG AST: Function name extracted from CallExpr reference: {}", name);
1579                } else if let Some(n) = ref_entity.get_name() {
1580                    name = n;
1581                }
1582            }
1583            
1584            // Debug: print all child entity kinds
1585            for (idx, c) in children.iter().enumerate() {
1586                debug_println!("DEBUG AST: CallExpr child[{}] kind: {:?}, name: {:?}, display_name: {:?}, reference: {:?}",
1587                    idx, c.get_kind(), c.get_name(), c.get_display_name(),
1588                    c.get_reference().map(|r| (r.get_kind(), r.get_name())));
1589                    
1590                // For member function calls, check for MemberRefExpr first
1591                if c.get_kind() == EntityKind::MemberRefExpr {
1592                    // MemberRefExpr can be either a method call OR a field access
1593                    // We need to distinguish between them
1594                    if let Some(ref_entity) = c.get_reference() {
1595                        debug_println!("DEBUG AST: MemberRefExpr references: {:?}", ref_entity.get_name());
1596                        if let Some(n) = ref_entity.get_name() {
1597                            if name == "unknown" {
1598                                // Build qualified name for member functions and constructors
1599                                if ref_entity.get_kind() == EntityKind::Method || ref_entity.get_kind() == EntityKind::Constructor {
1600                                    name = get_qualified_name(&ref_entity);
1601                                } else if ref_entity.get_kind() == EntityKind::FieldDecl {
1602                                    // This is a field access, not a function call
1603                                    // Don't use it as the function name - it will be extracted as MemberAccess
1604                                    debug_println!("DEBUG AST: MemberRefExpr is field access, not function name");
1605                                } else {
1606                                    name = n;
1607                                }
1608                            }
1609                        }
1610                    }
1611
1612                    // Debug: Check if MemberRefExpr has children (which might be the receiver object)
1613                    let member_children = c.get_children();
1614                    debug_println!("DEBUG AST: MemberRefExpr has {} children", member_children.len());
1615                    for (i, mc) in member_children.iter().enumerate() {
1616                        debug_println!("  DEBUG AST: MemberRefExpr child[{}]: kind={:?}, name={:?}",
1617                            i, mc.get_kind(), mc.get_name());
1618                    }
1619                } else if c.get_kind() == EntityKind::UnexposedExpr {
1620                    // Try to get the referenced entity
1621                    if let Some(ref_entity) = c.get_reference() {
1622                        debug_println!("DEBUG AST: UnexposedExpr references: {:?}", ref_entity.get_name());
1623                        if let Some(n) = ref_entity.get_name() {
1624                            if name == "unknown" {
1625                                name = n;
1626                            }
1627                        }
1628                    }
1629                    // Also try children of UnexposedExpr
1630                    for ue_child in c.get_children() {
1631                        debug_println!("DEBUG AST: UnexposedExpr child: kind={:?}, name={:?}, display_name={:?}", 
1632                            ue_child.get_kind(), ue_child.get_name(), ue_child.get_display_name());
1633                        
1634                        // Try to extract member function name from MemberRefExpr
1635                        if let Some(n) = ue_child.get_name() {
1636                            if name == "unknown" {
1637                                name = n;
1638                            }
1639                        } else if let Some(dn) = ue_child.get_display_name() {
1640                            if name == "unknown" && !dn.is_empty() {
1641                                name = dn;
1642                            }
1643                        }
1644                        
1645                        // Also check if this child has a reference
1646                        if let Some(ref_entity) = ue_child.get_reference() {
1647                            debug_println!("DEBUG AST: Child references: {:?}", ref_entity.get_name());
1648                            if let Some(n) = ref_entity.get_name() {
1649                                if name == "unknown" {
1650                                    name = n;
1651                                }
1652                            }
1653                        }
1654                    }
1655                }
1656            }
1657            
1658            // Two-pass approach:
1659            // Pass 1: Identify which child provides the function name
1660            // Pass 2: Extract arguments, handling MemberRefExpr specially if it's the name provider
1661
1662            let mut name_providing_child_idx: Option<usize> = None;
1663
1664            // CRITICAL FIX: If the method name was extracted from CallExpr's own reference
1665            // (common for template class methods), we need to find the MemberRefExpr child
1666            // and mark it as the name provider so the receiver can be extracted
1667            if method_name_from_callexpr {
1668                for (i, c) in children.iter().enumerate() {
1669                    if c.get_kind() == EntityKind::MemberRefExpr {
1670                        if let Some(ref_entity) = c.get_reference() {
1671                            if ref_entity.get_kind() == EntityKind::Method {
1672                                debug_println!("DEBUG AST: Found MemberRefExpr at index {} for method call", i);
1673                                name_providing_child_idx = Some(i);
1674                                break;
1675                            }
1676                        }
1677                    }
1678                }
1679            }
1680
1681            // Pass 1: Find the name-providing child
1682            if name_providing_child_idx.is_none() {
1683                if name == "unknown" {
1684                    for (i, c) in children.iter().enumerate() {
1685                        match c.get_kind() {
1686                            EntityKind::DeclRefExpr | EntityKind::UnexposedExpr => {
1687                                // CRITICAL FIX: EXCLUDE variables/parameters
1688                                // (which caused the "rhs"/"schema"/"vv" bugs)
1689                                if let Some(ref_entity) = c.get_reference() {
1690                                    let ref_kind = ref_entity.get_kind();
1691                                    if ref_kind == EntityKind::VarDecl || ref_kind == EntityKind::ParmDecl {
1692                                        continue; // Skip variables/parameters
1693                                    }
1694                                    // Bug #8 fix: Use qualified name for free functions too
1695                                    // This ensures namespace::function is captured correctly
1696                                    let n = get_qualified_name(&ref_entity);
1697                                    debug_println!("DEBUG AST: Got function name '{}' from reference (kind: {:?})", n, ref_entity.get_kind());
1698                                    name = n;
1699                                    name_providing_child_idx = Some(i);
1700                                    break;
1701                                }
1702                                // No reference - might be template-dependent, use name directly
1703                                if let Some(n) = c.get_name() {
1704                                    debug_println!("DEBUG AST: Got function name '{}' from name field", n);
1705                                    name = n;
1706                                    name_providing_child_idx = Some(i);
1707                                    break;
1708                                }
1709                            }
1710                            _ => {}
1711                        }
1712                    }
1713                } else {
1714                    // Name was already extracted, identify which child represents it
1715                    for (i, c) in children.iter().enumerate() {
1716                        match c.get_kind() {
1717                            EntityKind::DeclRefExpr | EntityKind::UnexposedExpr => {
1718                                if let Some(child_name) = c.get_name() {
1719                                    if name.ends_with(&child_name) || name == child_name {
1720                                        name_providing_child_idx = Some(i);
1721                                        break;
1722                                    }
1723                                }
1724                            }
1725                            _ => {}
1726                        }
1727                    }
1728                }
1729            }
1730
1731            // Pass 2: Extract arguments, handling MemberRefExpr specially if it's the name provider
1732            for (i, c) in children.into_iter().enumerate() {
1733                // If this child provided the function name
1734                if Some(i) == name_providing_child_idx {
1735                    // For method calls (MemberRefExpr is name provider), extract the receiver
1736                    if c.get_kind() == EntityKind::MemberRefExpr {
1737                        debug_println!("DEBUG AST: MemberRefExpr is name provider - extracting receiver");
1738                        // Extract receiver from MemberRefExpr's children
1739                        let member_children = c.get_children();
1740                        if !member_children.is_empty() {
1741                            // First child of MemberRefExpr is the receiver object
1742                            if let Some(recv_expr) = extract_expression(&member_children[0]) {
1743                                // Check if receiver type is a pointer (means -> was used)
1744                                // ptr->method() is semantically (*ptr).method(), so wrap in Dereference
1745                                // EXCEPT for safe smart pointers whose operator-> is safe
1746                                let is_arrow = member_children[0].get_type()
1747                                    .map(|t| matches!(t.get_kind(), TypeKind::Pointer))
1748                                    .unwrap_or(false);
1749
1750                                // Check if this is an overloaded operator-> (smart pointer)
1751                                // Raw pointers use built-in ->, smart pointers call operator->
1752                                let has_overloaded_arrow = if is_arrow {
1753                                    has_overloaded_arrow_operator(&member_children[0])
1754                                } else {
1755                                    false
1756                                };
1757
1758                                if is_arrow && !has_overloaded_arrow {
1759                                    debug_println!("DEBUG AST: Raw pointer arrow method call: (*{:?})", recv_expr);
1760                                    args.push(Expression::Dereference(Box::new(recv_expr)));
1761                                } else {
1762                                    debug_println!("DEBUG AST: Dot/smart pointer method call: {:?}", recv_expr);
1763                                    args.push(recv_expr);
1764                                }
1765                            }
1766                        } else {
1767                            // No children - the receiver might be implicit or a simple variable
1768                            // For a MemberRefExpr like m.content_size(), we need to extract "m"
1769                            // Unfortunately libclang doesn't always give us this directly
1770                            // We'll need to handle this case differently
1771                            debug_println!("DEBUG AST: MemberRefExpr has no children, cannot extract receiver");
1772                        }
1773                    }
1774                    // Skip the name-providing child itself
1775                    continue;
1776                }
1777
1778                // Extract all other children as normal arguments
1779                if let Some(expr) = extract_expression(&c) {
1780                    args.push(expr);
1781                }
1782            }
1783            
1784            // Check if this is std::move
1785            debug_println!("DEBUG: Found function call: name='{}', args_count={}", name, args.len());
1786            for (i, arg) in args.iter().enumerate() {
1787                debug_println!("  DEBUG: arg[{}] = {:?}", i, arg);
1788            }
1789            if is_move_function(&name) {
1790                debug_println!("DEBUG: Detected move function!");
1791                // std::move/rusty::move takes one argument and we treat it as a Move expression
1792                if args.len() == 1 {
1793                    let kind = get_move_kind(&name);
1794                    debug_println!("DEBUG: Creating Move expression with kind {:?}", kind);
1795                    return Some(Expression::Move {
1796                        inner: Box::new(args.into_iter().next().unwrap()),
1797                        kind,
1798                    });
1799                }
1800            }
1801            
1802            Some(Expression::FunctionCall { name, args })
1803        }
1804        EntityKind::UnexposedExpr => {
1805            // UnexposedExpr often wraps other expressions, so look at its children
1806            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1807            debug_println!("DEBUG EXTRACT: UnexposedExpr with name={:?}, {} children",
1808                entity.get_name(), children.len());
1809
1810            // Check if this UnexposedExpr has a reference (might be a method call)
1811            if let Some(ref_entity) = entity.get_reference() {
1812                debug_println!("  DEBUG EXTRACT: UnexposedExpr has reference: kind={:?}, name={:?}",
1813                    ref_entity.get_kind(), ref_entity.get_name());
1814            }
1815
1816            // If there are exactly 2 children, this might be a binary operation (e.g., assignment)
1817            if children.len() == 2 {
1818                debug_println!("  DEBUG EXTRACT: UnexposedExpr with 2 children - checking for binary op");
1819                if let (Some(left), Some(right)) =
1820                    (extract_expression(&children[0]), extract_expression(&children[1])) {
1821                    debug_println!("  DEBUG EXTRACT: Extracted both children, treating as assignment");
1822                    // UnexposedExpr with 2 operands is typically an assignment in a const method
1823                    // (C++ allows it syntactically even though it's a semantic error)
1824                    return Some(Expression::BinaryOp {
1825                        left: Box::new(left),
1826                        op: "=".to_string(),
1827                        right: Box::new(right),
1828                    });
1829                }
1830            }
1831
1832            // Otherwise, try to extract single child expression
1833            for child in children {
1834                debug_println!("  DEBUG EXTRACT: Child kind={:?}, name={:?}",
1835                    child.get_kind(), child.get_name());
1836
1837                // Check if child has a reference
1838                if let Some(child_ref) = child.get_reference() {
1839                    debug_println!("    DEBUG EXTRACT: Child has reference: kind={:?}, name={:?}",
1840                        child_ref.get_kind(), child_ref.get_name());
1841                }
1842
1843                if let Some(expr) = extract_expression(&child) {
1844                    debug_println!("  DEBUG EXTRACT: Returning {:?}", expr);
1845                    return Some(expr);
1846                }
1847            }
1848            debug_println!("  DEBUG EXTRACT: Returning None");
1849            None
1850        }
1851        EntityKind::BinaryOperator => {
1852            // Extract binary operation (e.g., i < 2, x == 0)
1853            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1854            if children.len() == 2 {
1855                if let (Some(left), Some(right)) = 
1856                    (extract_expression(&children[0]), extract_expression(&children[1])) {
1857                    // Try to get the operator from the entity's spelling
1858                    let op = entity.get_name().unwrap_or_else(|| "==".to_string());
1859                    return Some(Expression::BinaryOp {
1860                        left: Box::new(left),
1861                        op,
1862                        right: Box::new(right),
1863                    });
1864                }
1865            }
1866            None
1867        }
1868        EntityKind::IntegerLiteral => {
1869            // IntegerLiterals often have name=None, try display_name or tokens
1870            if let Some(name) = entity.get_name() {
1871                Some(Expression::Literal(name))
1872            } else if let Some(display) = entity.get_display_name() {
1873                Some(Expression::Literal(display))
1874            } else {
1875                // For integer literals, we can use a placeholder since we don't
1876                // need the actual value for ownership/borrow checking
1877                Some(Expression::Literal("0".to_string()))
1878            }
1879        }
1880        EntityKind::StringLiteral => {
1881            // String literals ("hello", L"wide", u8"utf8", etc.) have static lifetime
1882            // and are safe in @safe code - they cannot dangle.
1883            // Extract the string value from the entity
1884            debug_println!("DEBUG: Found StringLiteral entity");
1885            if let Some(name) = entity.get_name() {
1886                Some(Expression::StringLiteral(name))
1887            } else if let Some(display) = entity.get_display_name() {
1888                Some(Expression::StringLiteral(display))
1889            } else {
1890                // Even without the exact value, we know it's a string literal
1891                Some(Expression::StringLiteral("<string literal>".to_string()))
1892            }
1893        }
1894        EntityKind::ParenExpr => {
1895            // Parenthesized expression - just extract the inner expression
1896            // e.g., (*n) in (*n).value_ - we want to get the Dereference(n) inside
1897            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1898            if !children.is_empty() {
1899                debug_println!("DEBUG: ParenExpr has child: kind={:?}", children[0].get_kind());
1900                return extract_expression(&children[0]);
1901            }
1902            None
1903        }
1904        // C++ cast expressions - extract the inner expression
1905        // static_cast<T*>(ptr), dynamic_cast<T*>(ptr), reinterpret_cast<T*>(ptr), const_cast<T*>(ptr)
1906        // These are transparent for borrow checking - we care about what's being cast
1907        EntityKind::StaticCastExpr
1908        | EntityKind::DynamicCastExpr
1909        | EntityKind::ReinterpretCastExpr
1910        | EntityKind::ConstCastExpr
1911        | EntityKind::CStyleCastExpr => {
1912            // C++ cast expressions are unsafe operations in @safe code
1913            // Wrap the inner expression in Cast to track this
1914            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1915            // Find the expression being cast (not the type reference)
1916            for child in &children {
1917                if child.get_kind() != EntityKind::TypeRef {
1918                    if let Some(inner_expr) = extract_expression(child) {
1919                        return Some(Expression::Cast(Box::new(inner_expr)));
1920                    }
1921                }
1922            }
1923            // Even if we can't extract the inner expression, the cast itself is unsafe
1924            None
1925        }
1926        EntityKind::UnaryOperator => {
1927            // Check if it's address-of (&) or dereference (*)
1928            // Other unary operators (!, ~, -, +) should be treated as simple expressions
1929            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1930            if !children.is_empty() {
1931                if let Some(inner) = extract_expression(&children[0]) {
1932                    // Try to determine the operator type
1933                    // LibClang doesn't give us the operator directly, but we can check the types
1934                    if let Some(result_type) = entity.get_type() {
1935                        let type_str = type_to_string(&result_type);
1936
1937                        if let Some(child_type) = children[0].get_type() {
1938                            let child_type_str = type_to_string(&child_type);
1939
1940                            // If child is pointer and result is not, it's dereference (*)
1941                            if child_type_str.contains('*') && !type_str.contains('*') {
1942                                return Some(Expression::Dereference(Box::new(inner)));
1943                            }
1944                            // If child is not pointer but result is, it's address-of (&)
1945                            else if !child_type_str.contains('*') && type_str.contains('*') {
1946                                return Some(Expression::AddressOf(Box::new(inner)));
1947                            }
1948                            // Otherwise, it's a non-pointer unary operator (!, ~, -, +)
1949                            // These don't affect ownership/borrowing, so just return the inner expression
1950                            // wrapped in a BinaryOp with the operator for completeness
1951                            else {
1952                                // For borrow checking purposes, these operators are transparent
1953                                // Just return the inner expression since we don't need to track
1954                                // the arithmetic/logical operation
1955                                return Some(inner);
1956                            }
1957                        }
1958                    }
1959                    // If we couldn't get types, return inner expression (conservative: don't assume pointer op)
1960                    return Some(inner);
1961                }
1962            }
1963            None
1964        }
1965        EntityKind::MemberRefExpr => {
1966            // NEW: Parse member access expressions (obj.field)
1967            // MemberRefExpr is used for both field access and method calls
1968            // For field access, we extract: object from first child, field name from reference
1969            debug_println!("DEBUG: Found MemberRefExpr");
1970
1971            // Get the field/member name from the entity's reference or name
1972            let field_name = if let Some(ref_entity) = entity.get_reference() {
1973                debug_println!("DEBUG: MemberRefExpr references kind={:?}, name={:?}",
1974                    ref_entity.get_kind(), ref_entity.get_name());
1975                // Check if it's a field (not a method)
1976                if ref_entity.get_kind() == EntityKind::FieldDecl {
1977                    ref_entity.get_name().unwrap_or_else(|| "unknown_field".to_string())
1978                } else {
1979                    // It's a method call, not field access - return None to let CallExpr handle it
1980                    debug_println!("DEBUG: MemberRefExpr is method, not field");
1981                    return None;
1982                }
1983            } else if let Some(name) = entity.get_name() {
1984                debug_println!("DEBUG: MemberRefExpr has name={}", name);
1985                name
1986            } else {
1987                debug_println!("DEBUG: MemberRefExpr has no reference or name");
1988                "unknown_field".to_string()
1989            };
1990
1991            let children: Vec<Entity> = entity.get_children().into_iter().collect();
1992            if !children.is_empty() {
1993                // First child is the object being accessed (explicit object.field or ptr->field)
1994                if let Some(object_expr) = extract_expression(&children[0]) {
1995                    // Check if object type is a pointer (means -> was used, not .)
1996                    // ptr->field is semantically (*ptr).field, so wrap in Dereference
1997                    let child_type = children[0].get_type();
1998
1999                    let is_arrow = child_type
2000                        .map(|t| matches!(t.get_kind(), TypeKind::Pointer))
2001                        .unwrap_or(false);
2002
2003                    // Check if this is an overloaded operator-> (smart pointer)
2004                    // Raw pointers use built-in ->, smart pointers call operator->
2005                    let has_overloaded_arrow = if is_arrow {
2006                        has_overloaded_arrow_operator(&children[0])
2007                    } else {
2008                        false
2009                    };
2010
2011                    if is_arrow && !has_overloaded_arrow {
2012                        debug_println!("DEBUG: MemberRefExpr raw pointer arrow: (*{:?}).{}", object_expr, field_name);
2013                        return Some(Expression::MemberAccess {
2014                            object: Box::new(Expression::Dereference(Box::new(object_expr))),
2015                            field: field_name,
2016                        });
2017                    } else {
2018                        debug_println!("DEBUG: MemberRefExpr {} access: {:?}.{}",
2019                            if has_overloaded_arrow { "smart pointer" } else { "dot" },
2020                            object_expr, field_name);
2021                        return Some(Expression::MemberAccess {
2022                            object: Box::new(object_expr),
2023                            field: field_name,
2024                        });
2025                    }
2026                }
2027            } else {
2028                // No children means implicit 'this->field' access in a method
2029                // 'this' is guaranteed valid inside member functions, so NOT unsafe
2030                // (Unlike arbitrary raw pointers, 'this' cannot be null/invalid in well-formed code)
2031                debug_println!("DEBUG: MemberRefExpr implicit 'this' access: this.{}", field_name);
2032                return Some(Expression::MemberAccess {
2033                    object: Box::new(Expression::Variable("this".to_string())),
2034                    field: field_name,
2035                });
2036            }
2037            None
2038        }
2039        EntityKind::LambdaExpr => {
2040            // Extract lambda captures by analyzing the AST structure
2041            // In libclang, lambda captures appear as:
2042            // - Reference capture: VariableRef only (no DeclRefExpr for that variable)
2043            // - Copy capture: VariableRef + DeclRefExpr for the same variable
2044            // - Default capture ([&] or [=]): No VariableRef/DeclRefExpr, must check type fields
2045            // - The body is a CompoundStmt
2046            debug_println!("DEBUG LAMBDA PARSER: Found LambdaExpr!");
2047
2048            let mut captures = Vec::new();
2049
2050            // Collect all VariableRef entries (these are the captured variables)
2051            let mut var_refs: Vec<String> = Vec::new();
2052            // Collect all DeclRefExpr entries (these indicate copy captures)
2053            let mut decl_refs: std::collections::HashSet<String> = std::collections::HashSet::new();
2054            // Track if we found any explicit captures
2055            let mut has_explicit_captures = false;
2056            // Track if we found a move call (indicates move capture)
2057            let mut has_move_call = false;
2058
2059            for child in entity.get_children() {
2060                debug_println!("DEBUG LAMBDA child: kind={:?} name={:?}", child.get_kind(), child.get_name());
2061                match child.get_kind() {
2062                    EntityKind::VariableRef => {
2063                        has_explicit_captures = true;
2064                        if let Some(var_name) = child.get_name() {
2065                            var_refs.push(var_name);
2066                        }
2067                    }
2068                    EntityKind::DeclRefExpr => {
2069                        // DeclRefExpr indicates a copy capture (part of copy init expr)
2070                        if let Some(var_name) = child.get_name() {
2071                            decl_refs.insert(var_name);
2072                        }
2073                    }
2074                    EntityKind::CallExpr => {
2075                        // CallExpr with 'move' indicates a move capture [y = std::move(x)]
2076                        if let Some(name) = child.get_name() {
2077                            if name == "move" {
2078                                has_move_call = true;
2079                            }
2080                        }
2081                    }
2082                    EntityKind::ThisExpr => {
2083                        // Capturing 'this'
2084                        has_explicit_captures = true;
2085                        captures.push(LambdaCaptureKind::This);
2086                    }
2087                    _ => {}
2088                }
2089            }
2090
2091            // If no explicit captures found, check if lambda uses default capture
2092            // by looking at the source code range
2093            debug_println!("DEBUG LAMBDA: has_explicit_captures={}", has_explicit_captures);
2094            if !has_explicit_captures {
2095                // Try to get the source range and parse the capture specifier
2096                if let Some(range) = entity.get_range() {
2097                    if let Some(file) = range.get_start().get_file_location().file {
2098                        if let Ok(content) = std::fs::read_to_string(file.get_path()) {
2099                            let start_line = range.get_start().get_file_location().line as usize;
2100                            let start_col = range.get_start().get_file_location().column as usize;
2101                            debug_println!("DEBUG LAMBDA: Source parsing at line={} col={}", start_line, start_col);
2102
2103                            if let Some(line) = content.lines().nth(start_line.saturating_sub(1)) {
2104                                debug_println!("DEBUG LAMBDA: Line content: '{}'", line);
2105                                // Find the capture list: [...]
2106                                if let Some(bracket_start) = line.get(start_col.saturating_sub(1)..).and_then(|s| s.find('[')) {
2107                                    let search_start = start_col.saturating_sub(1) + bracket_start;
2108                                    if let Some(rest) = line.get(search_start..) {
2109                                        if let Some(bracket_end) = rest.find(']') {
2110                                            let capture_list = &rest[1..bracket_end];
2111                                            debug_println!("DEBUG LAMBDA: Capture list from source: '{}'", capture_list);
2112
2113                                            // Check for default reference capture [&]
2114                                            if capture_list.trim() == "&" {
2115                                                debug_println!("DEBUG LAMBDA: Default reference capture [&] detected");
2116                                                captures.push(LambdaCaptureKind::DefaultRef);
2117                                            }
2118                                            // Check for default copy capture [=]
2119                                            else if capture_list.trim() == "=" {
2120                                                debug_println!("DEBUG LAMBDA: Default copy capture [=] detected");
2121                                                captures.push(LambdaCaptureKind::DefaultCopy);
2122                                            }
2123                                            // Check for 'this' capture [this]
2124                                            else if capture_list.trim() == "this" {
2125                                                debug_println!("DEBUG LAMBDA: 'this' capture [this] detected");
2126                                                captures.push(LambdaCaptureKind::This);
2127                                            }
2128                                            // Check for '*this' capture [*this]
2129                                            else if capture_list.trim() == "*this" {
2130                                                debug_println!("DEBUG LAMBDA: '*this' capture [*this] detected");
2131                                                captures.push(LambdaCaptureKind::ThisCopy);
2132                                            }
2133                                            // Check for init captures [x = expr] or [x = std::move(y)]
2134                                            else if capture_list.contains('=') && !capture_list.starts_with('&') {
2135                                                // This is an init capture - safe (copy or move)
2136                                                debug_println!("DEBUG LAMBDA: Init capture detected");
2137                                                // Extract variable name before the '='
2138                                                if let Some(eq_pos) = capture_list.find('=') {
2139                                                    let var_name = capture_list[..eq_pos].trim().to_string();
2140                                                    let is_move = capture_list.contains("std::move") ||
2141                                                                 capture_list.contains("move(");
2142                                                    captures.push(LambdaCaptureKind::Init {
2143                                                        name: var_name,
2144                                                        is_move,
2145                                                    });
2146                                                }
2147                                            }
2148                                            // Check for explicit reference captures [&x, &y, ...]
2149                                            else if capture_list.starts_with('&') && !capture_list.contains(',') {
2150                                                // [&x] - single explicit reference capture
2151                                                // Already handled by VariableRef detection above
2152                                            }
2153                                        }
2154                                    }
2155                                }
2156                            }
2157                        }
2158                    }
2159                }
2160            }
2161
2162            // Determine capture type for each VariableRef (explicit captures)
2163            // Key insight from libclang patterns:
2164            // - Reference capture [&x]: VariableRef 'x' only (no DeclRefExpr, no CallExpr)
2165            // - Copy capture [x]: VariableRef 'x' + DeclRefExpr 'x' (same name)
2166            // - Init copy capture [y = x]: VariableRef 'y' + DeclRefExpr 'x' (different names, NO overlap!)
2167            // - Init move capture [y = std::move(x)]: VariableRef 'y' + CallExpr 'move'
2168            // - Mixed capture [x, &y]: VariableRef 'x' & 'y', DeclRefExpr 'x' only (partial overlap)
2169
2170            // Check if this is an init capture situation:
2171            // For init captures [y = x], var_refs and decl_refs have NO overlapping names
2172            let var_ref_set: std::collections::HashSet<_> = var_refs.iter().cloned().collect();
2173            let has_any_overlap = var_ref_set.intersection(&decl_refs).next().is_some();
2174            let is_init_capture_pattern = !decl_refs.is_empty() && !has_any_overlap;
2175
2176            for var_name in var_refs {
2177                if decl_refs.contains(&var_name) {
2178                    // Has corresponding DeclRefExpr with SAME name = copy capture
2179                    debug_println!("DEBUG LAMBDA: Copy capture of '{}'", var_name);
2180                    captures.push(LambdaCaptureKind::ByCopy(var_name));
2181                } else if has_move_call {
2182                    // Has move() call = init move capture [y = std::move(x)]
2183                    debug_println!("DEBUG LAMBDA: Init move capture '{}'", var_name);
2184                    captures.push(LambdaCaptureKind::Init {
2185                        name: var_name,
2186                        is_move: true,
2187                    });
2188                } else if is_init_capture_pattern {
2189                    // Has DeclRefExpr with entirely DIFFERENT names = init capture [y = x]
2190                    // The VariableRef is the new capture name, DeclRefExpr is the source
2191                    debug_println!("DEBUG LAMBDA: Init copy capture '{}'", var_name);
2192                    captures.push(LambdaCaptureKind::Init {
2193                        name: var_name,
2194                        is_move: false,
2195                    });
2196                } else {
2197                    // No matching DeclRefExpr = reference capture
2198                    debug_println!("DEBUG LAMBDA: Reference capture of '{}'", var_name);
2199                    captures.push(LambdaCaptureKind::ByRef(var_name));
2200                }
2201            }
2202
2203            debug_println!("DEBUG LAMBDA: Found lambda with {} captures: {:?}",
2204                captures.len(), captures);
2205
2206            Some(Expression::Lambda { captures })
2207        }
2208        EntityKind::ArraySubscriptExpr => {
2209            // Array subscript: arr[i], data[idx], etc.
2210            // The first child is the array/pointer, second is the index
2211            // For lifetime purposes, the source is the array (first child)
2212            let children: Vec<Entity> = entity.get_children().into_iter().collect();
2213            if !children.is_empty() {
2214                // First child is the array or pointer being indexed
2215                if let Some(array_expr) = extract_expression(&children[0]) {
2216                    debug_println!("DEBUG: ArraySubscriptExpr - array/pointer source: {:?}", array_expr);
2217                    // Return the array expression as the source
2218                    // This handles cases like data[i] returning reference to member data
2219                    return Some(array_expr);
2220                }
2221            }
2222            None
2223        }
2224        _ => None
2225    }
2226}
2227
2228fn extract_location(entity: &Entity) -> SourceLocation {
2229    let location = entity.get_location().unwrap();
2230    let file_location = location.get_file_location();
2231    
2232    SourceLocation {
2233        file: file_location
2234            .file
2235            .map(|f| f.get_path().display().to_string())
2236            .unwrap_or_else(|| "unknown".to_string()),
2237        line: file_location.line,
2238        column: file_location.column,
2239    }
2240}
2241
2242fn type_to_string(ty: &Type) -> String {
2243    ty.get_display_name()
2244}