fix(union): complete downstream container handling

This commit is contained in:
ctype_lab
2026-08-06 17:50:25 +09:00
parent e922563e05
commit e2195940fb
10 changed files with 136 additions and 32 deletions
+14 -12
View File
@@ -296,7 +296,7 @@ function resolveTypeName(name: string, objEnv: Map<string, string> | undefined):
let n = name;
for (let i = 0; objEnv && i < 5; i++) {
const v = objEnv.get(n);
const t = v?.trim().match(/^(?:struct\s+)?(\w+)$/);
const t = v?.trim().match(/^(?:(?:struct|union)\s+)?(\w+)$/);
if (!t) break;
n = t[1]!;
}
@@ -370,20 +370,20 @@ const INCLUDABLE_EXT = /\.(def|inc|h|hh|hpp|hxx|c|cc|cpp|cxx|ipp|tcc|tbl)$/i;
* are excluded: `resolveTypeName` would rewrite to a dead-end token that can
* never name a struct, so skipping them is exact, and it drops the register
* flood. */
const OBJ_ALIAS_RE = /^[ \t]*#[ \t]*define[ \t]+(\w+)[ \t]+(?:struct[ \t]+)*[A-Za-z_]\w*[ \t\r]*$/gm;
const OBJ_ALIAS_RE = /^[ \t]*#[ \t]*define[ \t]+(\w+)[ \t]+(?:(?:struct|union)[ \t]+)*[A-Za-z_]\w*[ \t\r]*$/gm;
/** `(?:struct )?TYPE name[opt] = {` initializers, where TYPE is a struct that
* has ≥1 fn-pointer field. Handles both single (`= {…}`) and array
* (`[] = { {…}, {…} }`) forms. Macro calls inside an element are expanded first. */
const INIT_RE =
/(?:^|[;{}])\s*(?:(?:static|const|extern|register|volatile)\s+)*(?:struct\s+)?(\w+)\s+(\w+)\s*(\[[^\]]*\])?\s*=\s*\{/g;
/(?:^|[;{}])\s*(?:(?:static|const|extern|register|volatile)\s+)*(?:(?:struct|union)\s+)?(\w+)\s+(\w+)\s*(\[[^\]]*\])?\s*=\s*\{/g;
/** `struct TAG { … } var[opt] [= {…}]` — the struct is defined INLINE with the
* table (vim's `cmdname`/`nv_cmd`); its layout never became a node, so parse it
* here and register it before reading the entries. No leading anchor: a
* `struct TAG {` with a brace body is always a definition (it may be preceded
* by a `#define …` line ending in a digit, as in vim), and the trailing
* `var … = {` check below is what distinguishes a TABLE from a plain type. */
const INLINE_STRUCT_RE = /\bstruct\s+(\w+)\s*\{/g;
const INLINE_STRUCT_RE = /\b(?:struct|union)\s+(\w+)\s*\{/g;
/** `(?:static …)* ELEMTYPE [*] name[…] = { … }` — a bare array of function
* pointers (no struct wrapper). The optional `*` covers a function-TYPE
* typedef element (`opcode_t *opcodes[]`); a function-pointer typedef element
@@ -854,12 +854,14 @@ export async function cFnPointerDispatchEdges(
if (fields.some((f) => f.isFnPtr)) structLayout.set(name, fields);
};
for (const st of (ctx.iterateNodesByKind?.('struct') ?? ctx.getNodesByKind('struct'))) {
if ((++scannedFiles & 255) === 0) await onYield();
if (!C_CPP_EXT.test(st.filePath)) continue;
const rawFields = rawFieldsByNode.get(st.id);
if (!rawFields) continue; // file unreadable or body unparsable at sweep time — the old pass skipped it too
registerStructLayout(st.name, classifyFields(rawFields));
for (const kind of ['struct', 'union'] as const) {
for (const st of (ctx.iterateNodesByKind?.(kind) ?? ctx.getNodesByKind(kind))) {
if ((++scannedFiles & 255) === 0) await onYield();
if (!C_CPP_EXT.test(st.filePath)) continue;
const rawFields = rawFieldsByNode.get(st.id);
if (!rawFields) continue; // file unreadable or body unparsable at sweep time — the old pass skipped it too
registerStructLayout(st.name, classifyFields(rawFields));
}
}
rawFieldsByNode.clear();
if (prof) { prof.B = Date.now() - tPass; tPass = Date.now(); }
@@ -1211,7 +1213,7 @@ export async function cFnPointerDispatchEdges(
const recvTypeIn = (fnSrc: string, recv: string): string | null => {
let re = recvReCache.get(recv);
if (!re) {
re = new RegExp(`(?:struct\\s+)?(\\w+)\\s*\\*?\\s*\\b${recv}\\b\\s*(?:[,)=;]|\\[)`, 'g');
re = new RegExp(`(?:(?:struct|union)\\s+)?(\\w+)\\s*\\*?\\s*\\b${recv}\\b\\s*(?:[,)=;]|\\[)`, 'g');
recvReCache.set(recv, re);
}
re.lastIndex = 0;
@@ -1230,7 +1232,7 @@ export async function cFnPointerDispatchEdges(
const varTypeIn = (fnSrc: string, v: string): string | null => {
let re = varReCache.get(v);
if (!re) {
re = new RegExp(`(?:struct\\s+)?(\\w+)\\s*\\*?\\s*\\b${escapeRe(v)}\\b\\s*(?:[,)=;]|\\[)`, 'g');
re = new RegExp(`(?:(?:struct|union)\\s+)?(\\w+)\\s*\\*?\\s*\\b${escapeRe(v)}\\b\\s*(?:[,)=;]|\\[)`, 'g');
varReCache.set(v, re);
}
re.lastIndex = 0;
+1 -1
View File
@@ -2192,7 +2192,7 @@ function findExportedSymbolWalk(
/** Node kinds that own static members reachable as `Container.member`. */
const STATIC_MEMBER_CONTAINERS = new Set<Node['kind']>([
'class', 'struct', 'interface', 'enum', 'trait', 'protocol',
'class', 'struct', 'union', 'interface', 'enum', 'trait', 'protocol',
]);
/**