fix(cpp): correct args counting for operator() and constructors with initializer-lists - #2275
Merged
Merged
Conversation
…initializer-lists
Two distinct, independently-diagnosed bugs in C++ args counting:
Pattern 1 (zero-undercount): operator() and out-of-class methods with
non-whitelisted parameter types (e.g. mlir::ModuleOp) reported args=0.
Root cause was two-fold: (a) _calculate_block_metrics's regex-based
args extraction rejects operator() syntax and enforces a rigid
parameter-type whitelist, silently defaulting to 0 on failure -- now
falls back to the structural _count_top_level_args counter for c/cpp
when the regex path fails, since func_start already validated this is
a real function; (b) _count_top_level_args itself needed to skip
operator()'s own empty name-parens to find the real parameter-list
parens.
Pattern 2 (off-by-one overcount): a zero-arg constructor with a
member-initializer-list (`Ctor() : member(x) { }`) reported args=1 --
_slice_by_braces's args_search_text swept the initializer-list clause
into the parameter-list search, misreading `member(x)` as a
parameter. Fixed by truncating args_search_text at the first
top-level `:` (excluding `::`) before the opening brace.
Both fixes gated to lang_id/primary_lang_id in ("c", "cpp"); the
common case (real params + initializer list) is unaffected.
Confirmed via inline synthetic repro: operator()(a,b) 0->2,
out-of-class BuildBuffer(mlir::ModuleOp) 0->1, zero-arg ctor with
init-list 1->0, normal ctor with params+init-list unchanged at 2,
operator() call-site correctly still excluded.
Closes #2012
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2012. Two distinct, independently-diagnosed bugs in C++ args counting:
Pattern 1 (zero-undercount):
operator()and out-of-class methods with non-whitelisted parameter types (e.g.mlir::ModuleOp) reportedargs=0. Root cause was two-fold: (a) the regex-based args extraction rejectsoperator()syntax and enforces a rigid parameter-type whitelist, silently defaulting to 0 on failure; (b) the structural fallback counter needed to skipoperator()'s own empty name-parens to find the real parameter-list parens.Pattern 2 (off-by-one overcount): a zero-arg constructor with a member-initializer-list (
Ctor() : member(x) { }) reportedargs=1-- the args-search text swept the initializer-list clause into the parameter-list search, misreadingmember(x)as a parameter.Fix
:(excluding::) before the opening brace, cutting the initializer-list clause out of the search entirely (Pattern 2)._count_top_level_argscounter for c/cpp when the regex path fails, sincefunc_startalready validated it's a real function (Pattern 1a).operator()'s own empty name-parens in that structural counter to find the real parameter list (Pattern 1b).Both fixes gated to
lang_id/primary_lang_id in ("c", "cpp"). The common case (real params + initializer list) is unaffected.Evidence
operator()(a, b)BuildBuffer(mlir::ModuleOp module)Corpus-wide:
args_exact_matchimproved from 1233 to 1295 (out of 1296/1297 comparable functions).Known minor limitation
The
operator()detection uses an 8-character trailing substring match (args_str[open_idx-8:open_idx] == "operator") without a word-boundary check. An identifier ending in...operator(with no separator before it (e.g. a hypotheticalcustom_operator(...)) could theoretically false-positive and skip a real first parameter list. No such case was found in the ~80-repo corpus; flagging for awareness rather than blocking on it.Verification
pytest tests/core_engine/test_detector.py tests/extraction/languages/test_cpp.py -q-- 195 passed (1 new regression test covering both patterns + the unaffected common case)audit_check.py --ci-- cleancrucible_check.py --mode both-- drift confined to cpp (NVDA/godot/mlir Function Analysis changes, attributable) plus expected global mass/coordinate ripple in unrelated directory groups (confirmed no Function Analysis changes outside cpp), blessedtree_sitter_accuracy_audit.py --all --ci-- cleantri_comparison_chart.py --all --ci-- cleanThis touches shared
detector.pyhelpers (_calculate_block_metrics,_count_top_level_args), so the full--all --cisweep was run per repo convention.🤖 Generated with Gemini (via
agy), orchestrated and independently verified by Claude Code.