A class, struct or union whose declaration writes its name in a scope —
leveldb's `struct SkipList<Key, Comparator>::Node { … }`, rocksdb's
`struct BlockBasedTable::Rep { … }` — was indexed as `<anonymous>`, so its
members belonged to no class anyone names and a call on a `Node*` or `Rep*`
was guessed by the method's name. Such a class now takes its own name,
qualified under the written scope the way an out-of-line method is, and its
members are qualified under it, in the TS extractor and the kernel alike. A
specialization (`struct fmt::formatter<Answer>`) stays unnamed: named after
its template, it stood in for the template and every other specialization.
Constructions are recorded by the type's last name, so with `DBImpl::Writer`
named, leveldb's `new log::Writer(…)` in `DBImpl` methods went to it. A C++
construction now makes the class C++ lookup finds for the type as written at
the construction (matchCppConstruction): read with its template arguments
(`new Outer<int>::Inner(…)` makes an `Outer::Inner`), at 0.9, or 0.7 when it
is only the class of that name the file can see; an enum lookup finds; through
an alias the calling function declares, the class it names; and nothing for a
template parameter, a member of a type from outside the project or a local
alias of one. Of several classes or aliases the file declares under one
qualified name (the local classes of separate gtest TEST_F bodies, the members
of unnamed specializations), the one declared around the construction. A `<`
or `>` in parentheses inside template arguments is now read as a comparison.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tree-sitter-cpp has no preprocessor, so an attribute macro where it
expects a name or a type misparses the declaration around it. The C++
preParse already blanked one export macro before a class name, an inline
macro before a return type, and a lone macro line before a declaration.
It missed:
- several macros, or one with arguments, between `class` and the name
(protobuf's generated `class PROTOBUF_EXPORT
PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Any final : public Message`,
rocksdb's `struct ALIGN_AS(64U) HandleImpl`), and a macro before a
partial specialization's name;
- a macro between a pointer and the declared name (`const Descriptor*
PROTOBUF_NONNULL descriptor()`), after a parameter list
(`unknown_fields() const ABSL_ATTRIBUTE_LIFETIME_BOUND {`, leveldb's
`LOCKS_EXCLUDED(mu_) {`), after a declared name (`int count_
GUARDED_BY(mu_);`), or opening a declaration
(`PROTOBUF_FUTURE_ADD_EARLY_NODISCARD absl::string_view name() const`);
- a lone macro line with a comment under it ({fmt}'s
`FMT_BEGIN_EXPORT` above `// A generic formatting context ...`).
Every generated protobuf message class misparsed, so its members were
indexed as namespace-level functions; leveldb's annotated methods became
phantoms named after the annotation.
The new passes match on the code alone (comments and directives as
spaces, literals as placeholders), blank only the macro tokens, and keep
every offset. They run in the hoisted preParse, so files that now parse
clean go through the native kernel, at parity. The passes share one mask
per file: a pass that blanks nothing hands the next the same string, and
one that blanks hands it the mask blanked the same way.
#2426's brace-scope fixtures misparsed only through
PROTOBUF_FUTURE_ADD_EARLY_NODISCARD and ALIGN_AS(64U), which the preParse
now blanks. They now use macros it doesn't know (NODISCARD,
cacheline_aligned(64U)), with the same expected scopes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(cpp): macro invocations are not calls; local objects call their constructor
A function-like macro invocation (`TRACE_POINT(1)`) parses as a call, and
the resolver bound it to a same-named free function in another translation
unit — a caller and a callee that never existed (#1838). And local object
initialization (`Widget w;` / `Widget w(1);` / `Widget w{1};`) reached the
class node instead of a constructor, or nothing at all for the default
form (#1839).
Extraction (wasm walker and the Rust kernel, in parity):
- every `preproc_function_def` becomes a `constant` node whose signature
is the directive, so the index knows which names are macros;
- a C++ declaration emits one `calls` ref per constructed object, shaped
`ns::T::T/<arity>`; pointer, reference and function declarators,
`extern`, and array element braces construct nothing; the #1035
`instantiates` ref is unchanged;
- constructors carry their parameter list as the signature.
Resolution:
- `cpp-macro-visibility.ts` walks the translation unit (root file plus
in-repo includes, each file once) over per-file summaries of
function-like defines, undefs and includes, evaluating what each file
can decide itself (literals, its own defines, the include-guard idiom).
A call whose name is definitely a macro at that point, or a name that
only macros bear, resolves to nothing. A macro that exists in one build
configuration only (CMSIS's `__DSB()` under the ARM compilers, a
target's HAL compat header) keeps the call to the function the other
configuration compiles; a wrapper macro that calls its own name is how
that function gets called and hides nothing.
- `cpp-constructor.ts` resolves the constructor refs: the type in the
lexical namespaces of the call site, then the single overload whose
parameter count admits the arguments; two admitting overloads, an
initializer_list overload, or an aggregate yield no edge.
- a `#define` constant is never a `calls` target and does not count
toward the same-name ceiling.
Measured on a betaflight tree (4,017 files, wasm arm): 153 `calls` edges
lost — all fabricated (`MIN`/`MAX` bound to a CLI enum member, macros
misparsed as functions, a cross-vendor `SWAPBYTE`) — and 34 constructor
edges gained; indexing 34s vs 30s.
Fixes#1838Fixes#1839
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(cpp): resolve local constructors and macro visibility (#1839)
Local construction lacked constructor calls, while macro invocations could bind unrelated functions.
Resolve constructors using lexical types and overload signatures, preserving separately declared defaults and array element construction.
Evaluate macro directives in translation-unit order, respecting reinclusion, guards and pragma once.
Mirror extraction in Rust and WASM, preserve type dependencies, and distinguish them in CLI output.
Co-authored-by: danusha2345 <danusha2345@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: danusha2345 <danusha2345@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
MSVC COM interface declarations were parsed as functions, losing their owners and methods.
Normalize declaration-position interface keywords to padded struct keywords when alias or declaration evidence is present.
Preserve source offsets and protected text through the shared native/WASM preprocessing hook.
Cover real-file indexing, inheritance, source retrieval, and parser parity.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Single-argument function macros were indexed under parentheses in C or the macro name in C++, breaking caller resolution.
Recover both parser shapes only when a preceding local macro definition establishes the function name, and mirror the recovery in the Rust kernel.
Preserve existing multi-argument recovery and ordinary declarations; add extraction, resolution, explore-flow, and parity regressions.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Parity: 0 diffs on redis/git/fmt/protobuf/ALS sweeps; full-init dumps
byte-identical on all five + linux at kernel scale (10.4M dump lines,
same sha256 both arms). Linux 2c/6GB envelope: kernel-arm 19.1min vs
wasm-arm 22.9min (parse 356s vs 435s) on a much richer graph (the new
blanks recover error-swallowed code: git 2x nodes, linux kernel/+mm/ 3x).
Deferral guard corrected by measurement (C/C++ error incidence 9-42%;
--max-deferral flag); defer-reuse memo kills the 3x re-blank/re-parse
cost deferred files paid.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>