From 0f9be719058c14682e1a040cf732f9813f070a8e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:44:30 +0000 Subject: [PATCH] test(cpp): cover non-type template args and std ADL ambiguity boundary Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/d8701678-a06a-477a-9c6d-312fd4c54f17 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> --- gitnexus/src/core/ingestion/languages/cpp/adl.ts | 6 ++++++ .../core/ingestion/languages/cpp/scope-resolver.ts | 6 ++++-- .../lang-resolution/cpp-adl-template-args/app.cpp | 10 ++++++++++ .../lang-resolution/cpp-adl-template-args/audit.h | 7 +++++++ gitnexus/test/integration/resolvers/cpp.test.ts | 13 +++++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/gitnexus/src/core/ingestion/languages/cpp/adl.ts b/gitnexus/src/core/ingestion/languages/cpp/adl.ts index 0eac14f05..5fa380e92 100644 --- a/gitnexus/src/core/ingestion/languages/cpp/adl.ts +++ b/gitnexus/src/core/ingestion/languages/cpp/adl.ts @@ -188,6 +188,9 @@ export function pickCppAdlCandidates( if (arg.isReference) continue; if (arg.simpleClassName !== '') { + // For template args this may be the template name itself (e.g. + // `vector`); simple-name lookup can match project classes with the + // same name (known V1/V2 simplification). const classDef = findCppClassDefBySimpleName(arg.simpleClassName, scopes); if (classDef !== undefined) { const nsQName = classToNamespaceQualifiedName.get(classDef.nodeId); @@ -195,6 +198,9 @@ export function pickCppAdlCandidates( } } + // Includes template-owner namespaces (e.g. `std` in std::vector). + // If that surfaces extra candidates, ADL_AMBIGUOUS suppression below + // prevents arbitrary edge emission. if (arg.templateNamespace.length > 0) associatedNamespaces.add(arg.templateNamespace); for (const ns of arg.templateArgNamespaces) { diff --git a/gitnexus/src/core/ingestion/languages/cpp/scope-resolver.ts b/gitnexus/src/core/ingestion/languages/cpp/scope-resolver.ts index 431717d27..a4d41e8b4 100644 --- a/gitnexus/src/core/ingestion/languages/cpp/scope-resolver.ts +++ b/gitnexus/src/core/ingestion/languages/cpp/scope-resolver.ts @@ -222,8 +222,10 @@ export const cppScopeResolver: ScopeResolver = { // C++ argument-dependent / Koenig lookup (U2 of plan 2026-05-13-001). // Fires after `findCallableBindingInScope` returns undefined; surfaces // candidates from the associated namespaces of class-typed arguments. - // V1 limitation: only direct enclosing-namespace closure for value - // class-typed args; pointer/reference/template-spec args excluded. + // Current boundary: class-typed value/pointer args and template + // specializations with explicit type arguments contribute associated + // namespaces. Reference args, function-pointer args, base-class + // associated namespaces, and full ordinary+ADL merge remain excluded. resolveAdlCandidates: (site, callerParsed, scopes, parsedFiles) => { // `using ns::name;` introduces `name` into ordinary unqualified lookup. // For template-class method bodies, lexical scope walks can miss this diff --git a/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/app.cpp b/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/app.cpp index 91af89399..5673ee229 100644 --- a/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/app.cpp +++ b/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/app.cpp @@ -10,4 +10,14 @@ namespace app { std::map> m; applyNested(m); } + + void runArray() { + std::array a; + applyArray(a); + } + + void runStdConflict() { + std::vector v; + applyStdConflict(v); + } } diff --git a/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/audit.h b/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/audit.h index c229879e8..e59392f89 100644 --- a/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/audit.h +++ b/gitnexus/test/fixtures/lang-resolution/cpp-adl-template-args/audit.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,4 +10,10 @@ namespace N { void apply(std::vector v); void applyNested(std::map> m); + void applyArray(std::array a); + void applyStdConflict(std::vector v); +} + +namespace std { + void applyStdConflict(vector v); } diff --git a/gitnexus/test/integration/resolvers/cpp.test.ts b/gitnexus/test/integration/resolvers/cpp.test.ts index fa92f9b92..0723f5533 100644 --- a/gitnexus/test/integration/resolvers/cpp.test.ts +++ b/gitnexus/test/integration/resolvers/cpp.test.ts @@ -2248,6 +2248,19 @@ describe('C++ ADL — template specialization args contribute associated namespa expect(applyCalls.length).toBe(1); expect(applyCalls[0].targetFilePath).toContain('audit.h'); }); + + it('applyArray(a) where a is std::array resolves to N::applyArray (non-type arg ignored)', () => { + const calls = getRelationships(result, 'CALLS'); + const applyCalls = calls.filter((c) => c.source === 'runArray' && c.target === 'applyArray'); + expect(applyCalls.length).toBe(1); + expect(applyCalls[0].targetFilePath).toContain('audit.h'); + }); + + it('applyStdConflict(v) is suppressed when ADL surfaces both N and std candidates', () => { + const calls = getRelationships(result, 'CALLS'); + const applyCalls = calls.filter((c) => c.source === 'runStdConflict' && c.target === 'applyStdConflict'); + expect(applyCalls.length).toBe(0); + }); }); describe('C++ ADL — int/long-collision overloads suppress via OVERLOAD_AMBIGUOUS', () => {