Skip to content

C extractor: functions with #ifdef-split braces are dropped from the graph (no Function node) #961

Description

@DeusData

Summary

A C function whose body braces are split across #ifdef/#else branches is silently dropped from the code knowledge graph — no Function node is emitted for it, even though its callers remain and reference it as an unresolved name.

Root cause

The extractor parses raw source with tree-sitter without running the preprocessor, so both #ifdef branches are present at once. When a construct like this opens a brace in each branch but shares one close brace:

#ifdef _WIN32
    if (a() && b()) {      // open brace (branch 1)
        ...
#else
    if (c() && d()) {      // a different open brace (branch 2)
#endif
        ...shared body...
    }                      // single shared close brace

tree-sitter sees two if { opens and one } close → unbalanced braces → an ERROR node spanning the function body → no Function node is created. Recovery is localized (neighbouring functions extract fine), so the symptom is one function silently absent.

Reproduction (reproduce-first)

Found via a graph-vs-grep audit: cbm_path_within_root in src/mcp/mcp.c was absent from the graph while its 6 callers were present. Refactoring that specific function to a single unconditional control flow (#960) made it index. The general pattern remains unhandled.

Suggested RED reproduction for the bug-repro suite: a fixture C function with the #ifdef-splits-brace shape, asserting a Function node is produced for it. It should fail on the current extractor and pass once the extractor handles the pattern.

Impact

Low frequency but real: any function using this (uncommon) preprocessor pattern is invisible to search_graph/trace_path/callers, and dead-code / impact analysis will misjudge it. Also a latent correctness gap for graph-based audits.

Possible directions (extractor-side, harder than the per-function workaround)

  • Detect the ERROR-node-spanning-a-definition case and attempt a light preprocessor pass (pick one #ifdef branch) before re-parsing that region.
  • Or a targeted brace-rebalancing heuristic for #ifdef/#else/#endif regions inside a definition.

Not urgent; filing so the limitation is tracked rather than rediscovered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/normalStandard review queue; useful PR with ordinary maintainer urgency.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions