mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-10 03:27:59 +00:00
merge: sync origin/main into ADL template branch
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/ac900193-369d-473b-a5d6-56c78341cae0 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
This commit is contained in:
parent
0f9be71905
commit
113b54f7ca
10 changed files with 121 additions and 18 deletions
|
|
@ -15,13 +15,14 @@
|
|||
*
|
||||
* ## Current boundary
|
||||
*
|
||||
* The current implementation covers class-typed arguments (value and pointer)
|
||||
* and template specializations with explicit type arguments:
|
||||
* The current implementation covers class-typed arguments (value, pointer,
|
||||
* and reference) and template specializations with explicit type arguments:
|
||||
* - `audit::Event e`, `audit::Event* p`, `audit::Event** pp`
|
||||
* - `audit::Event& r`, `audit::Event&& rr`
|
||||
* - `std::vector<audit::Event>` (template namespace + template-arg namespaces)
|
||||
*
|
||||
* Reference arguments, function-pointer arguments, base-class associated
|
||||
* namespaces, and the rest of the full closure are still deliberately excluded.
|
||||
* Function-pointer arguments, base-class associated namespaces, and the rest
|
||||
* of the full closure are still deliberately excluded.
|
||||
*
|
||||
* The current implementation also short-circuits to ADL only when ordinary lookup is empty
|
||||
* (`findCallableBindingInScope` returned undefined). ISO C++ would
|
||||
|
|
@ -61,8 +62,8 @@ import {
|
|||
|
||||
/**
|
||||
* Per-argument shape information collected at capture time. ADL fires for
|
||||
* arguments where `simpleClassName !== ''` AND `!isReference`, including
|
||||
* class pointers whose declarator chain resolves to a named class type.
|
||||
* arguments where `simpleClassName !== ''`, including class pointers and
|
||||
* references whose declarator chain resolves to a named class type.
|
||||
*/
|
||||
export interface CppAdlArgInfo {
|
||||
/** Simple class-like type name (last segment of qualified name); empty
|
||||
|
|
@ -163,8 +164,8 @@ export function populateCppAssociatedNamespaces(parsed: ParsedFile): void {
|
|||
*
|
||||
* Fires only when:
|
||||
* - the call site is not in `noAdlSites` (parenthesized form), AND
|
||||
* - at least one argument resolves to a named class type (value or
|
||||
* pointer, but not reference, function pointer, literal, or primitive).
|
||||
* - at least one argument resolves to a named class type (value,
|
||||
* pointer, or reference; but not function pointer, literal, or primitive).
|
||||
*/
|
||||
export function pickCppAdlCandidates(
|
||||
site: {
|
||||
|
|
@ -185,8 +186,6 @@ export function pickCppAdlCandidates(
|
|||
// Collect associated namespace QNames from every participating class-typed arg.
|
||||
const associatedNamespaces = new Set<string>();
|
||||
for (const arg of args) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -803,13 +803,14 @@ function lookupAdlIdentifierType(identNode: SyntaxNode): CppAdlArgInfo {
|
|||
// Unwrap declarator chain to find pointer/reference markers and the
|
||||
// variable name. `init_declarator > pointer_declarator > identifier`
|
||||
// means pointer-typed; repeated pointer wrappers still count as pointer
|
||||
// typed; `init_declarator > reference_declarator > ...` means
|
||||
// reference-typed; bare `init_declarator > identifier` is value.
|
||||
// typed; `init_declarator > reference_declarator > ...` (or
|
||||
// `rvalue_reference_declarator`) means reference-typed; bare
|
||||
// `init_declarator > identifier` is value.
|
||||
// Function-pointer wrappers (`pointer_declarator > function_declarator`)
|
||||
// must not contribute ADL associated namespaces.
|
||||
let isFunctionPointer = false;
|
||||
let isPointer = false;
|
||||
let isReference = false;
|
||||
let isFunctionPointer = false;
|
||||
let inner: SyntaxNode = declarator;
|
||||
let nameText: string | null = null;
|
||||
let safety = 16; // bound walk depth defensively
|
||||
|
|
@ -825,7 +826,7 @@ function lookupAdlIdentifierType(identNode: SyntaxNode): CppAdlArgInfo {
|
|||
inner = next;
|
||||
continue;
|
||||
}
|
||||
if (inner.type === 'reference_declarator') {
|
||||
if (inner.type === 'reference_declarator' || inner.type === 'rvalue_reference_declarator') {
|
||||
isReference = true;
|
||||
// reference_declarator has a single child (the inner declarator).
|
||||
let next: SyntaxNode | null = null;
|
||||
|
|
|
|||
|
|
@ -222,10 +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.
|
||||
// Current boundary: class-typed value/pointer args and template
|
||||
// Current boundary: class-typed value/pointer/reference 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.
|
||||
// namespaces. 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
|
||||
|
|
|
|||
21
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/app.cpp
vendored
Normal file
21
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/app.cpp
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "audit.h"
|
||||
|
||||
namespace app {
|
||||
void runRef() {
|
||||
audit::Event e;
|
||||
audit::Event& s = e;
|
||||
record(s);
|
||||
}
|
||||
|
||||
void runConstRef() {
|
||||
audit::Event e;
|
||||
const audit::Event& constEventRef = e;
|
||||
recordConst(constEventRef);
|
||||
}
|
||||
|
||||
void runPrimitiveRef() {
|
||||
int n = 0;
|
||||
int& r = n;
|
||||
note(r);
|
||||
}
|
||||
}
|
||||
5
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/audit.h
vendored
Normal file
5
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/audit.h
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
namespace audit {
|
||||
struct Event {};
|
||||
}
|
||||
8
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/record.h
vendored
Normal file
8
gitnexus/test/fixtures/lang-resolution/cpp-adl-reference-arg-boundary/record.h
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "audit.h"
|
||||
|
||||
namespace audit {
|
||||
void record(Event& e);
|
||||
void recordConst(const Event& e);
|
||||
}
|
||||
9
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/app.cpp
vendored
Normal file
9
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/app.cpp
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#include "audit.h"
|
||||
|
||||
namespace app {
|
||||
void runRvalueRef() {
|
||||
audit::Event e;
|
||||
audit::Event&& rr = static_cast<audit::Event&&>(e);
|
||||
record(rr);
|
||||
}
|
||||
}
|
||||
5
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/audit.h
vendored
Normal file
5
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/audit.h
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
namespace audit {
|
||||
struct Event {};
|
||||
}
|
||||
7
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/record-rvalue.h
vendored
Normal file
7
gitnexus/test/fixtures/lang-resolution/cpp-adl-rvalue-ref/record-rvalue.h
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "audit.h"
|
||||
|
||||
namespace audit {
|
||||
void record(Event&& e);
|
||||
}
|
||||
|
|
@ -2103,7 +2103,7 @@ describe('C++ two-phase template lookup — cross-file namespace variant', () =>
|
|||
// Free-function calls with class-typed arguments must consider candidates
|
||||
// declared in the argument's enclosing namespace (associated namespace).
|
||||
// V1 boundary: only direct enclosing-namespace closure for value class-
|
||||
// typed args; pointer / reference / template-spec args excluded.
|
||||
// typed args; pointer and reference args included, template-spec args excluded.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('C++ ADL — basic associated-namespace closure', () => {
|
||||
|
|
@ -2161,6 +2161,54 @@ describe('C++ ADL — pointer arg unwrapping', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('C++ ADL — reference arg unwrapping', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
beforeAll(async () => {
|
||||
result = await runPipelineFromRepo(
|
||||
path.join(FIXTURES, 'cpp-adl-reference-arg-boundary'),
|
||||
() => {},
|
||||
);
|
||||
}, 60000);
|
||||
|
||||
it('record(s) where s is audit::Event& resolves to audit::record via ADL', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const recordCalls = calls.filter((c) => c.source === 'runRef' && c.target === 'record');
|
||||
expect(recordCalls.length).toBe(1);
|
||||
expect(recordCalls[0].targetFilePath).toContain('record.h');
|
||||
});
|
||||
|
||||
it('recordConst(cs) where cs is const audit::Event& resolves via ADL', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const recordCalls = calls.filter(
|
||||
(c) => c.source === 'runConstRef' && c.target === 'recordConst',
|
||||
);
|
||||
expect(recordCalls.length).toBe(1);
|
||||
expect(recordCalls[0].targetFilePath).toContain('record.h');
|
||||
});
|
||||
|
||||
it('note(r) where r is int& emits zero CALLS edges (primitive ref)', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const noteCalls = calls.filter((c) => c.source === 'runPrimitiveRef' && c.target === 'note');
|
||||
expect(noteCalls.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('C++ ADL — rvalue reference args participate', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
beforeAll(async () => {
|
||||
result = await runPipelineFromRepo(path.join(FIXTURES, 'cpp-adl-rvalue-ref'), () => {});
|
||||
}, 60000);
|
||||
|
||||
it('record(rr) where rr is audit::Event&& resolves to audit::record via ADL', () => {
|
||||
const calls = getRelationships(result, 'CALLS');
|
||||
const recordCalls = calls.filter((c) => c.source === 'runRvalueRef' && c.target === 'record');
|
||||
expect(recordCalls.length).toBe(1);
|
||||
expect(recordCalls[0].targetFilePath).toContain('record-rvalue.h');
|
||||
});
|
||||
});
|
||||
|
||||
describe('C++ ADL — function pointer args do not participate', () => {
|
||||
let result: PipelineResult;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue