Skip to content

fix(extract): attribute calls inside out-of-line C++ methods to the method#621

Draft
KerseyFabrications wants to merge 3 commits into
DeusData:mainfrom
KerseyFabrications:fix/out-of-line-namespace-attribution
Draft

fix(extract): attribute calls inside out-of-line C++ methods to the method#621
KerseyFabrications wants to merge 3 commits into
DeusData:mainfrom
KerseyFabrications:fix/out-of-line-namespace-attribution

Conversation

@KerseyFabrications

Copy link
Copy Markdown
Contributor

Follow-up to #463 (out-of-line attribution gap reported there).

Problem

A call inside a C++ out-of-line method definition attributes to the File node instead of the enclosing method — including when the definition is
wrapped in a namespace {} block.

Root cause

Not namespace context (which never enters the C++ QN scheme — namespace_name is null and the namespace appears in no QN), but a dropped class
qualifier
. The call-side enclosing-QN computation produced project.path.Bar instead of project.path.Foo.Bar for out-of-line defs (no enclosing class
AST node / no class scope on the walk stack). The pipeline resolves a call's source by exact QN (calls_find_sourcefind_by_qn), so the mismatch falls
straight back to the __file__ node. Identical for the global (using namespace) and namespace-block forms.

Fix

The out-of-line class resolution lived in the defs extractor but had two divergent, incomplete copies on the call side — the same drift behind #438.
Consolidated rather than adding a fourth copy:

  • cbm_cpp_out_of_line_parent_class — promoted from extract_defs.c into helpers.
  • cbm_cpp_out_of_line_method_qn — new shared helper building the class-scoped QN, used by both compute_func_qn (CALLS, unified walk) and
    cbm_enclosing_func_qn (cached path: USAGES/THROWS/CONFIGURES/type-assigns).

Corrects attribution for every edge type inside out-of-line methods, not just CALLS.

Tests

  • cpp_out_of_line_enclosing_qn — extraction-level QN match for global / namespace-block / nested-namespace forms.
  • pipeline_cpp_out_of_line_call_attribution — full index of a header + using namespace .cc + namespace {} .cc; both Baz() calls source from the
    Method node, not the file.

Full suite green apart from a pre-existing, unrelated ASan RSS-budget flake.

Note on stacking

Based on the #463 branch tip, so until #463 merges this PR shows both commits; the first is #463's dedup and drops automatically once #463 lands. #463
itself is unchanged.

A CALLS edge whose caller is a C/C++/CUDA/GLSL function was sourced to the
file's Module node instead of the calling Function. "Find callers of X"
returned a file path, outbound trace_path returned empty, and
(:Function)-[:CALLS]->(:Function) queries missed for these languages.

Root cause: the enclosing-function resolvers read only tree-sitter's `name`
field, but a `function_definition` node has none — the name lives in the
declarator chain (pointer/function/parenthesized/array declarators). So
func_node_name() (internal/cbm/helpers.c) and resolve_func_name_node()
(internal/cbm/extract_unified.c) returned NULL, the enclosing scope fell
back to the module QN, and the edge was attributed to the Module node. This
is the C counterpart to DeusData#220, which fixed the definition-naming path but not
the enclosing-call path.

Fix: descend the declarator chain to the innermost name node (mirroring
resolve_c_declarator_name in extract_defs.c, including qualified and operator
names) when a function_definition lacks a `name` field. Adds the regression
test c_caller_attribution asserting a C call's enclosing_func_qn is the
function, not the module.

Fixes DeusData#438

Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
Addresses DeusData#463 review: the declarator-chain name resolver was copied into
helpers.c, extract_unified.c, and extract_defs.c, and CBM_DECLARATOR_DEPTH_LIMIT
was #defined twice -- the same triplication drift that caused DeusData#438.

- Add cbm_resolve_c_declarator_name_node() to helpers.{c,h} as the single
  source of truth, carrying is_c_terminal_name/resolve_qualified_name with it.
- Route the defs, calls, and unified extractors through it.
- Hoist CBM_DECLARATOR_DEPTH_LIMIT into helpers.h; extract_defs.c's
  DECLARATOR_DEPTH_LIMIT now derives from it.

Canonicalizes on the original extract_defs.c logic (operator/destructor aware)
so defs behavior is unchanged and calls/unified now agree with it.

Test: full suite green except an unrelated ASan RSS-budget check; clang-format clean.

Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
…ethod

A call inside a C++ out-of-line method definition (void Foo::Bar() { ... })
attributes to the File node instead of the enclosing method, including when the
definition is wrapped in a namespace block (reported on DeusData#463).

Root cause is not namespace context (absent from the C++ QN scheme) but a dropped
class qualifier: the call-side enclosing-QN computation produced t.path.Bar instead
of t.path.Foo.Bar for out-of-line definitions (no enclosing class AST node / no
class scope on the walk stack), so the pipeline's exact-QN source match fell back
to __file__. Same for the global (using-namespace) and namespace-block forms.

The out-of-line class resolution existed in the defs extractor but had two
divergent, incomplete copies on the call side -- the drift that caused DeusData#438.
Consolidate instead of adding a fourth copy:
- cbm_cpp_out_of_line_parent_class: promoted from extract_defs.c into helpers.
- cbm_cpp_out_of_line_method_qn: new shared helper that builds the class-scoped QN,
  used by both compute_func_qn (CALLS, unified walk) and cbm_enclosing_func_qn
  (cached path: USAGES/THROWS/CONFIGURES/type-assigns).

Fixes attribution for every edge type inside out-of-line methods, not just CALLS.

Tests: cpp_out_of_line_enclosing_qn (extraction QN match for global/block/nested)
and pipeline_cpp_out_of_line_call_attribution (full index: both forms source the
CALLS edge from a Method node). Full suite green apart from an unrelated, pre-existing
ASan RSS-budget flake.

Signed-off-by: Kris Kersey <kris@kerseyfabrications.com>
@KerseyFabrications KerseyFabrications marked this pull request as draft June 25, 2026 04:04
@KerseyFabrications

Copy link
Copy Markdown
Contributor Author

This was converted to draft until #463 is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant