fix(c): blank leading attribute macros so functions index under real names (#1311)
SEC_ATTR UINT32 LostName(VOID) — an unknown attribute macro before a
typedef'd return type — misparses in tree-sitter's C grammar: the macro
becomes the type, the return type the declarator, and the PARAMETER
LIST is stored as the function name ("(VOID)"). The C++ grammar
recovers this shape via recoverMangledCppName, but in C the real name
never reaches the mangled string, so only a pre-parse blank can help.
Attribute macros are project-specific, so the blank keys on structure:
line-leading ALL-CAPS token followed by TWO identifiers then `(` — the
`MACRO Ret name(` definition shape. Plain typedef'd returns, ALL-CAPS
calls, #define lines, multi-word builtin returns, and mid-line uses are
all rejected by construction. Offset-preserving like the C++ blanks.
curl re-index: 5,531 C functions before and after, zero name changes;
7 nodes in memdebug.c improve start-line accuracy by 1 (the macro line
no longer counts as part of the definition).
Fixes #1211
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e437918026
commit
b6a05d155b
@@ -709,11 +709,47 @@ function preParseCppSource(source: string, filePath?: string): string {
|
||||
return blanked;
|
||||
}
|
||||
|
||||
/** C source pre-processing: C-detected headers in CUDA projects (llm.c keeps
|
||||
* `__device__` helpers and kernel prototypes in plain `.h`) get the same
|
||||
* content-gated CUDA blank as C++. */
|
||||
/**
|
||||
* Blank an unknown attribute macro sitting in front of a C function
|
||||
* definition's return type: `SEC_ATTR UINT32 LostName(VOID) { … }` (macro
|
||||
* wrapping `__attribute__((…))`, common in embedded/kernel C). tree-sitter's
|
||||
* C grammar reads the macro as the declaration's type, the real return type
|
||||
* as the declarator, and stores the PARAMETER LIST as the function name —
|
||||
* `LostName` indexes as `"(VOID)"` and is unfindable (#1211). The C++ grammar
|
||||
* recovers this shape differently (glued name, salvaged post-hoc by
|
||||
* `recoverMangledCppName`), but in C the real name never reaches the mangled
|
||||
* string, so only a pre-parse blank can recover it.
|
||||
*
|
||||
* Attribute macros are project-specific (`SEC_ATTR`, `INIT_TEXT`, …), so this
|
||||
* keys on structure, not a curated list, matched tightly:
|
||||
* - line-leading (`^[ \t]*`) — declaration position, never an expression use;
|
||||
* - ALL-CAPS token of ≥3 chars (`[A-Z][A-Z0-9_]{2,}`) — ordinary C types in
|
||||
* definitions are rarely spelled this way, and when they are (`UINT32 f()`)
|
||||
* they're followed by ONE identifier + `(`, which the lookahead rejects;
|
||||
* - followed by TWO identifier tokens (return type, then name — `*` allowed
|
||||
* for pointer returns) and then `(` — i.e. exactly the
|
||||
* `MACRO Ret name(` definition shape. `MACRO name(` calls, `#define`
|
||||
* lines (start with `#`), and multi-word builtin returns
|
||||
* (`MACRO unsigned int f(` — where the C grammar already keeps the name)
|
||||
* are all left untouched.
|
||||
* Equal-length spaces preserve every byte offset, like the C++ blanks above.
|
||||
*/
|
||||
const C_LEADING_ATTR_MACRO_RE =
|
||||
/^([ \t]*)([A-Z][A-Z0-9_]{2,})(?=\s+[A-Za-z_]\w*[\s*]+[A-Za-z_]\w*\s*\()/gm;
|
||||
export function blankCLeadingAttrMacros(source: string): string {
|
||||
return source.replace(
|
||||
C_LEADING_ATTR_MACRO_RE,
|
||||
(_m, ws: string, macro: string) => ws + ' '.repeat(macro.length)
|
||||
);
|
||||
}
|
||||
|
||||
/** C source pre-processing: recover functions hidden behind a leading
|
||||
* attribute macro (#1211), then — for C-detected headers in CUDA projects
|
||||
* (llm.c keeps `__device__` helpers and kernel prototypes in plain `.h`) —
|
||||
* the same content-gated CUDA blank as C++. Offset-preserving. */
|
||||
function preParseCSource(source: string): string {
|
||||
return looksLikeCudaSource(source) ? blankCudaConstructs(source) : source;
|
||||
const blanked = blankCLeadingAttrMacros(source);
|
||||
return looksLikeCudaSource(blanked) ? blankCudaConstructs(blanked) : blanked;
|
||||
}
|
||||
|
||||
export const cppExtractor: LanguageExtractor = {
|
||||
|
||||
Reference in New Issue
Block a user