Skip to content

CALLS edges are emitted for calls inside statically-dead code (if False:, if TYPE_CHECKING:, #if 0) #576

Description

@HouMinXi

Summary

The graph indexes function calls that occur inside statically-unreachable code as ordinary live CALLS edges. Because the parse is structural (Tree-sitter, no reachability analysis and no C preprocessor evaluation), downstream consumers cannot distinguish a call that can execute from one that never will.

Reproduction (Python)

# consumer.py
from api import process_request

def live_caller():
    process_request()          # line 5

def dead_caller():
    if False:                  # statically dead
        process_request()      # line 10 -- never executes
code-review-graph build --skip-flows

Resulting edges (both present):

CALLS  consumer.py::dead_caller -> process_request   line 10
CALLS  consumer.py::live_caller -> process_request   line 5

The dead_caller edge should not be presented as a live call.

Reproduction (C/C++)

A call inside a #if 0 ... #endif block is likewise emitted as a live CALLS edge (observed on a real C++ project: a call inside a #if 0 block was indexed identically to the active code path).

Impact

Any consumer doing impact analysis / caller discovery over CALLS edges gets false positives from dead code: "symbol X is called at <dead site>", when that site can never run.

Suggestion

Either (a) skip emitting CALLS edges whose call expression is inside an obviously-dead construct, or (b) tag such edges (e.g. reachable=0 / a "dead-code" confidence_tier) so consumers can filter. The common cheap-to-detect idioms cover most of the value:

  • Python: if False: / if 0: / if TYPE_CHECKING: ; code after an unconditional return/raise/break/continue
  • C/C++: #if 0 ... #endif (and #ifdef of an undefined macro)

Full reachability is undecidable and not expected; handling these common static-dead idioms would remove the bulk of the false positives.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions