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>