selfhost: structlookup/enumlookup mod-filter (mirror aliaslookup)
Tags structinfo/enumtype with originating module; exact-match first, then split pkg.X and filter by smod/emod. Without this, two modules with same-leaf-name struct/enum types collapsed to whichever entry appeared first in the chain. Wired into 696_modtype_leaf_collision via a wwstage run_pos using ww_ww (negative case omitted: w6c_ww has no checkfile pass). Updated the test's Makefile deps to include the wwstage binaries. Audited the rest of the lookup family — fnretlookup, fnparamslookup, deflookup don't need the same treatment: the parser emits N_DOT.str (call/field name) as the leaf only, and fnparamslookup is only invoked with N_IDENT.str. Dotted module-qualified function calls go through the module-mangling path instead.
This commit is contained in:
1
Makefile
1
Makefile
@@ -356,6 +356,7 @@ $(BIN)/test_match_bind_struct: test/wcc/695_match_bind_struct.c $(BIN)/ww \
|
|||||||
|
|
||||||
$(BIN)/test_modtype_leaf_collision: test/wcc/696_modtype_leaf_collision.c \
|
$(BIN)/test_modtype_leaf_collision: test/wcc/696_modtype_leaf_collision.c \
|
||||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||||
|
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
|
||||||
$(LIB)/libwwrt.a | $(BIN)
|
$(LIB)/libwwrt.a | $(BIN)
|
||||||
$(CC) $(CFLAGS) -o $@ $<
|
$(CC) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
|||||||
@@ -6878,12 +6878,41 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
|||||||
// ---- type-driven slot sizing ----------------------------------------
|
// ---- type-driven slot sizing ----------------------------------------
|
||||||
|
|
||||||
fn structlookup(c: *cgen, name: str) *structinfo = {
|
fn structlookup(c: *cgen, name: str) *structinfo = {
|
||||||
|
// Exact match first: bare-from-source struct names and already-
|
||||||
|
// leafed lookups hit here directly.
|
||||||
let s: *structinfo = c.structs;
|
let s: *structinfo = c.structs;
|
||||||
for (s != nil) {
|
for (s != nil) {
|
||||||
let sn: str = s.sname;
|
let sn: str = s.sname;
|
||||||
if (streq(sn, name)) { return s; };
|
if (streq(sn, name)) { return s; };
|
||||||
s = s.sinext;
|
s = s.sinext;
|
||||||
};
|
};
|
||||||
|
// Module-qualified form: `pkg.S` → match the leaf scoped to its
|
||||||
|
// originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `smod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name structs from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
|
let i: i32 = name.len - 1;
|
||||||
|
for (i >= 0) {
|
||||||
|
if (name[i] == 46u8) { // '.'
|
||||||
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
|
leaf.len = name.len - (i + 1);
|
||||||
|
let b: *structinfo = c.structs;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.sname, leaf)) {
|
||||||
|
if (streq(b.smod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.sinext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
i -= 1;
|
||||||
|
};
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7229,9 +7258,10 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = {
|
|||||||
return 8;
|
return 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
fn registerstruct(c: *cgen, name: str, tstruct: *node) void = {
|
fn registerstruct(c: *cgen, name: str, module: str, tstruct: *node) void = {
|
||||||
let si: *structinfo = amalloc(c.a, 64u64): *structinfo;
|
let si: *structinfo = amalloc(c.a, 80u64): *structinfo;
|
||||||
si.sname = name;
|
si.sname = name;
|
||||||
|
si.smod = module;
|
||||||
si.fields = nil;
|
si.fields = nil;
|
||||||
si.totsize = 0;
|
si.totsize = 0;
|
||||||
let head: *fieldinfo = nil;
|
let head: *fieldinfo = nil;
|
||||||
@@ -7279,7 +7309,7 @@ fn collectstructs(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TSTRUCT) {
|
if (body.kind == nkind.N_TSTRUCT) {
|
||||||
registerstruct(c, d.str, body);
|
registerstruct(c, d.str, d.module, body);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -15529,8 +15559,9 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TENUM) {
|
if (body.kind == nkind.N_TENUM) {
|
||||||
let et: *enumtype = amalloc(c.a, 48u64): *enumtype;
|
let et: *enumtype = amalloc(c.a, 64u64): *enumtype;
|
||||||
et.ename = d.str;
|
et.ename = d.str;
|
||||||
|
et.emod = d.module;
|
||||||
et.storage = body.lhs;
|
et.storage = body.lhs;
|
||||||
et.members = nil;
|
et.members = nil;
|
||||||
let prev: u64 = (-1i64): u64;
|
let prev: u64 = (-1i64): u64;
|
||||||
@@ -15566,24 +15597,40 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
||||||
// Strip any `pkg.` prefix and key off the leaf — driver-side
|
// Exact match first: bare-from-source idents and already-leafed
|
||||||
// concatenation flattens the namespace, so `os.whence` and
|
// names hit here directly.
|
||||||
// `whence` refer to the same registered enum.
|
let e: *enumtype = c.enums;
|
||||||
let leaf: str = name;
|
for (e != nil) {
|
||||||
|
if (streq(e.ename, name)) { return e; };
|
||||||
|
e = e.etnext;
|
||||||
|
};
|
||||||
|
// Module-qualified form: `pkg.enum` → match the leaf scoped to
|
||||||
|
// its originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `emod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name enums from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
let i: i32 = name.len - 1;
|
let i: i32 = name.len - 1;
|
||||||
for (i >= 0) {
|
for (i >= 0) {
|
||||||
if (name[i] == 46u8) { // '.'
|
if (name[i] == 46u8) { // '.'
|
||||||
leaf.ptr = name.ptr + (i + 1): u64;
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
leaf.len = name.len - (i + 1);
|
leaf.len = name.len - (i + 1);
|
||||||
break;
|
let b: *enumtype = c.enums;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.ename, leaf)) {
|
||||||
|
if (streq(b.emod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.etnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
};
|
};
|
||||||
i -= 1;
|
i -= 1;
|
||||||
};
|
};
|
||||||
let e: *enumtype = c.enums;
|
|
||||||
for (e != nil) {
|
|
||||||
if (streq(e.ename, leaf)) { return e; };
|
|
||||||
e = e.etnext;
|
|
||||||
};
|
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -15633,6 +15680,7 @@ type fieldinfo = struct {
|
|||||||
|
|
||||||
type structinfo = struct {
|
type structinfo = struct {
|
||||||
sname: str,
|
sname: str,
|
||||||
|
smod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
fields: *fieldinfo,
|
fields: *fieldinfo,
|
||||||
totsize: i32,
|
totsize: i32,
|
||||||
sinext: *structinfo,
|
sinext: *structinfo,
|
||||||
@@ -15676,6 +15724,7 @@ type enummember = struct {
|
|||||||
|
|
||||||
type enumtype = struct {
|
type enumtype = struct {
|
||||||
ename: str,
|
ename: str,
|
||||||
|
emod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
storage: *node, // AST type expr for the storage type (i32 by default)
|
storage: *node, // AST type expr for the storage type (i32 by default)
|
||||||
members: *enummember,
|
members: *enummember,
|
||||||
etnext: *enumtype,
|
etnext: *enumtype,
|
||||||
|
|||||||
@@ -179,8 +179,9 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TENUM) {
|
if (body.kind == nkind.N_TENUM) {
|
||||||
let et: *enumtype = amalloc(c.a, 48u64): *enumtype;
|
let et: *enumtype = amalloc(c.a, 64u64): *enumtype;
|
||||||
et.ename = d.str;
|
et.ename = d.str;
|
||||||
|
et.emod = d.module;
|
||||||
et.storage = body.lhs;
|
et.storage = body.lhs;
|
||||||
et.members = nil;
|
et.members = nil;
|
||||||
let prev: u64 = (-1i64): u64;
|
let prev: u64 = (-1i64): u64;
|
||||||
@@ -216,24 +217,40 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
||||||
// Strip any `pkg.` prefix and key off the leaf — driver-side
|
// Exact match first: bare-from-source idents and already-leafed
|
||||||
// concatenation flattens the namespace, so `os.whence` and
|
// names hit here directly.
|
||||||
// `whence` refer to the same registered enum.
|
let e: *enumtype = c.enums;
|
||||||
let leaf: str = name;
|
for (e != nil) {
|
||||||
|
if (streq(e.ename, name)) { return e; };
|
||||||
|
e = e.etnext;
|
||||||
|
};
|
||||||
|
// Module-qualified form: `pkg.enum` → match the leaf scoped to
|
||||||
|
// its originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `emod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name enums from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
let i: i32 = name.len - 1;
|
let i: i32 = name.len - 1;
|
||||||
for (i >= 0) {
|
for (i >= 0) {
|
||||||
if (name[i] == 46u8) { // '.'
|
if (name[i] == 46u8) { // '.'
|
||||||
leaf.ptr = name.ptr + (i + 1): u64;
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
leaf.len = name.len - (i + 1);
|
leaf.len = name.len - (i + 1);
|
||||||
break;
|
let b: *enumtype = c.enums;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.ename, leaf)) {
|
||||||
|
if (streq(b.emod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.etnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
};
|
};
|
||||||
i -= 1;
|
i -= 1;
|
||||||
};
|
};
|
||||||
let e: *enumtype = c.enums;
|
|
||||||
for (e != nil) {
|
|
||||||
if (streq(e.ename, leaf)) { return e; };
|
|
||||||
e = e.etnext;
|
|
||||||
};
|
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -283,6 +300,7 @@ type fieldinfo = struct {
|
|||||||
|
|
||||||
type structinfo = struct {
|
type structinfo = struct {
|
||||||
sname: str,
|
sname: str,
|
||||||
|
smod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
fields: *fieldinfo,
|
fields: *fieldinfo,
|
||||||
totsize: i32,
|
totsize: i32,
|
||||||
sinext: *structinfo,
|
sinext: *structinfo,
|
||||||
@@ -326,6 +344,7 @@ type enummember = struct {
|
|||||||
|
|
||||||
type enumtype = struct {
|
type enumtype = struct {
|
||||||
ename: str,
|
ename: str,
|
||||||
|
emod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
storage: *node, // AST type expr for the storage type (i32 by default)
|
storage: *node, // AST type expr for the storage type (i32 by default)
|
||||||
members: *enummember,
|
members: *enummember,
|
||||||
etnext: *enumtype,
|
etnext: *enumtype,
|
||||||
|
|||||||
@@ -1149,12 +1149,41 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
|||||||
// ---- type-driven slot sizing ----------------------------------------
|
// ---- type-driven slot sizing ----------------------------------------
|
||||||
|
|
||||||
fn structlookup(c: *cgen, name: str) *structinfo = {
|
fn structlookup(c: *cgen, name: str) *structinfo = {
|
||||||
|
// Exact match first: bare-from-source struct names and already-
|
||||||
|
// leafed lookups hit here directly.
|
||||||
let s: *structinfo = c.structs;
|
let s: *structinfo = c.structs;
|
||||||
for (s != nil) {
|
for (s != nil) {
|
||||||
let sn: str = s.sname;
|
let sn: str = s.sname;
|
||||||
if (streq(sn, name)) { return s; };
|
if (streq(sn, name)) { return s; };
|
||||||
s = s.sinext;
|
s = s.sinext;
|
||||||
};
|
};
|
||||||
|
// Module-qualified form: `pkg.S` → match the leaf scoped to its
|
||||||
|
// originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `smod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name structs from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
|
let i: i32 = name.len - 1;
|
||||||
|
for (i >= 0) {
|
||||||
|
if (name[i] == 46u8) { // '.'
|
||||||
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
|
leaf.len = name.len - (i + 1);
|
||||||
|
let b: *structinfo = c.structs;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.sname, leaf)) {
|
||||||
|
if (streq(b.smod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.sinext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
i -= 1;
|
||||||
|
};
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1500,9 +1529,10 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = {
|
|||||||
return 8;
|
return 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
fn registerstruct(c: *cgen, name: str, tstruct: *node) void = {
|
fn registerstruct(c: *cgen, name: str, module: str, tstruct: *node) void = {
|
||||||
let si: *structinfo = amalloc(c.a, 64u64): *structinfo;
|
let si: *structinfo = amalloc(c.a, 80u64): *structinfo;
|
||||||
si.sname = name;
|
si.sname = name;
|
||||||
|
si.smod = module;
|
||||||
si.fields = nil;
|
si.fields = nil;
|
||||||
si.totsize = 0;
|
si.totsize = 0;
|
||||||
let head: *fieldinfo = nil;
|
let head: *fieldinfo = nil;
|
||||||
@@ -1550,7 +1580,7 @@ fn collectstructs(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TSTRUCT) {
|
if (body.kind == nkind.N_TSTRUCT) {
|
||||||
registerstruct(c, d.str, body);
|
registerstruct(c, d.str, d.module, body);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6878,12 +6878,41 @@ fn nodeprimwidth(c: *cgen, n: *node) i32 = {
|
|||||||
// ---- type-driven slot sizing ----------------------------------------
|
// ---- type-driven slot sizing ----------------------------------------
|
||||||
|
|
||||||
fn structlookup(c: *cgen, name: str) *structinfo = {
|
fn structlookup(c: *cgen, name: str) *structinfo = {
|
||||||
|
// Exact match first: bare-from-source struct names and already-
|
||||||
|
// leafed lookups hit here directly.
|
||||||
let s: *structinfo = c.structs;
|
let s: *structinfo = c.structs;
|
||||||
for (s != nil) {
|
for (s != nil) {
|
||||||
let sn: str = s.sname;
|
let sn: str = s.sname;
|
||||||
if (streq(sn, name)) { return s; };
|
if (streq(sn, name)) { return s; };
|
||||||
s = s.sinext;
|
s = s.sinext;
|
||||||
};
|
};
|
||||||
|
// Module-qualified form: `pkg.S` → match the leaf scoped to its
|
||||||
|
// originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `smod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name structs from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
|
let i: i32 = name.len - 1;
|
||||||
|
for (i >= 0) {
|
||||||
|
if (name[i] == 46u8) { // '.'
|
||||||
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
|
leaf.len = name.len - (i + 1);
|
||||||
|
let b: *structinfo = c.structs;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.sname, leaf)) {
|
||||||
|
if (streq(b.smod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.sinext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
|
};
|
||||||
|
i -= 1;
|
||||||
|
};
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7229,9 +7258,10 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = {
|
|||||||
return 8;
|
return 8;
|
||||||
};
|
};
|
||||||
|
|
||||||
fn registerstruct(c: *cgen, name: str, tstruct: *node) void = {
|
fn registerstruct(c: *cgen, name: str, module: str, tstruct: *node) void = {
|
||||||
let si: *structinfo = amalloc(c.a, 64u64): *structinfo;
|
let si: *structinfo = amalloc(c.a, 80u64): *structinfo;
|
||||||
si.sname = name;
|
si.sname = name;
|
||||||
|
si.smod = module;
|
||||||
si.fields = nil;
|
si.fields = nil;
|
||||||
si.totsize = 0;
|
si.totsize = 0;
|
||||||
let head: *fieldinfo = nil;
|
let head: *fieldinfo = nil;
|
||||||
@@ -7279,7 +7309,7 @@ fn collectstructs(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TSTRUCT) {
|
if (body.kind == nkind.N_TSTRUCT) {
|
||||||
registerstruct(c, d.str, body);
|
registerstruct(c, d.str, d.module, body);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -15529,8 +15559,9 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
let body: *node = d.lhs;
|
let body: *node = d.lhs;
|
||||||
if (body != nil) {
|
if (body != nil) {
|
||||||
if (body.kind == nkind.N_TENUM) {
|
if (body.kind == nkind.N_TENUM) {
|
||||||
let et: *enumtype = amalloc(c.a, 48u64): *enumtype;
|
let et: *enumtype = amalloc(c.a, 64u64): *enumtype;
|
||||||
et.ename = d.str;
|
et.ename = d.str;
|
||||||
|
et.emod = d.module;
|
||||||
et.storage = body.lhs;
|
et.storage = body.lhs;
|
||||||
et.members = nil;
|
et.members = nil;
|
||||||
let prev: u64 = (-1i64): u64;
|
let prev: u64 = (-1i64): u64;
|
||||||
@@ -15566,24 +15597,40 @@ fn collectenums(c: *cgen, file: *node) void = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
fn enumlookup(c: *cgen, name: str) *enumtype = {
|
||||||
// Strip any `pkg.` prefix and key off the leaf — driver-side
|
// Exact match first: bare-from-source idents and already-leafed
|
||||||
// concatenation flattens the namespace, so `os.whence` and
|
// names hit here directly.
|
||||||
// `whence` refer to the same registered enum.
|
let e: *enumtype = c.enums;
|
||||||
let leaf: str = name;
|
for (e != nil) {
|
||||||
|
if (streq(e.ename, name)) { return e; };
|
||||||
|
e = e.etnext;
|
||||||
|
};
|
||||||
|
// Module-qualified form: `pkg.enum` → match the leaf scoped to
|
||||||
|
// its originating module. Mirrors aliaslookup's mod-filter; the
|
||||||
|
// `emod == pkg` guard is what prevents two modules with same-
|
||||||
|
// leaf-name enums from collapsing into whichever entry appears
|
||||||
|
// first in the chain.
|
||||||
let i: i32 = name.len - 1;
|
let i: i32 = name.len - 1;
|
||||||
for (i >= 0) {
|
for (i >= 0) {
|
||||||
if (name[i] == 46u8) { // '.'
|
if (name[i] == 46u8) { // '.'
|
||||||
leaf.ptr = name.ptr + (i + 1): u64;
|
let pkg: str;
|
||||||
|
pkg.ptr = name.ptr;
|
||||||
|
pkg.len = i;
|
||||||
|
let leaf: str;
|
||||||
|
leaf.ptr = name.ptr + ((i + 1): u64);
|
||||||
leaf.len = name.len - (i + 1);
|
leaf.len = name.len - (i + 1);
|
||||||
break;
|
let b: *enumtype = c.enums;
|
||||||
|
for (b != nil) {
|
||||||
|
if (streq(b.ename, leaf)) {
|
||||||
|
if (streq(b.emod, pkg)) {
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
b = b.etnext;
|
||||||
|
};
|
||||||
|
return nil;
|
||||||
};
|
};
|
||||||
i -= 1;
|
i -= 1;
|
||||||
};
|
};
|
||||||
let e: *enumtype = c.enums;
|
|
||||||
for (e != nil) {
|
|
||||||
if (streq(e.ename, leaf)) { return e; };
|
|
||||||
e = e.etnext;
|
|
||||||
};
|
|
||||||
return nil;
|
return nil;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -15633,6 +15680,7 @@ type fieldinfo = struct {
|
|||||||
|
|
||||||
type structinfo = struct {
|
type structinfo = struct {
|
||||||
sname: str,
|
sname: str,
|
||||||
|
smod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
fields: *fieldinfo,
|
fields: *fieldinfo,
|
||||||
totsize: i32,
|
totsize: i32,
|
||||||
sinext: *structinfo,
|
sinext: *structinfo,
|
||||||
@@ -15676,6 +15724,7 @@ type enummember = struct {
|
|||||||
|
|
||||||
type enumtype = struct {
|
type enumtype = struct {
|
||||||
ename: str,
|
ename: str,
|
||||||
|
emod: str, // originating module (`// MODULE: foo`), or empty
|
||||||
storage: *node, // AST type expr for the storage type (i32 by default)
|
storage: *node, // AST type expr for the storage type (i32 by default)
|
||||||
members: *enummember,
|
members: *enummember,
|
||||||
etnext: *enumtype,
|
etnext: *enumtype,
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ main(void)
|
|||||||
|
|
||||||
char cdrv[1024];
|
char cdrv[1024];
|
||||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||||
|
char wdrv[1024];
|
||||||
|
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||||
|
|
||||||
char fixdir[1024];
|
char fixdir[1024];
|
||||||
if (getcwd(fixdir, sizeof fixdir) == NULL) return 1;
|
if (getcwd(fixdir, sizeof fixdir) == NULL) return 1;
|
||||||
@@ -108,12 +110,18 @@ main(void)
|
|||||||
int fail = 0;
|
int fail = 0;
|
||||||
fail += run_pos(cdrv, fixdir, "cstage");
|
fail += run_pos(cdrv, fixdir, "cstage");
|
||||||
fail += run_neg(cdrv, fixdir, "cstage");
|
fail += run_neg(cdrv, fixdir, "cstage");
|
||||||
|
fail += run_pos(wdrv, fixdir, "wwstage");
|
||||||
|
/* No wwstage neg case: w6c_ww has no checkfile pass, so a
|
||||||
|
* missing-field reference doesn't surface as a build error.
|
||||||
|
* The positive case alone pins the structlookup mod-filter
|
||||||
|
* (without it, `mod2.stream` would either fail to resolve or
|
||||||
|
* silently bind to mod1.stream and miscompute the exit). */
|
||||||
|
|
||||||
if (fail) {
|
if (fail) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"modtype_leaf_collision: %d case(s) failed\n", fail);
|
"modtype_leaf_collision: %d case(s) failed\n", fail);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("modtype_leaf_collision: 2/2 ok\n");
|
printf("modtype_leaf_collision: 3/3 ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user