fix(Handles): 多继承字段展平按继承源去重,消除菱形重复
Generator 同时继承 ClassGenMixin/ClassGenEnum/ClassGenGeneric/ClassGenVTable/ClassGenDef/ClassGenBase,而前 5 个都继承 ClassGenBase → ClassGenBase 41 字段被重复展平 6 次(struct 707 元素),class_members 索引与 struct 布局错位 → 跨 Mixin 方法 this_adjust 失效 → is_exception_name 读错位内存 strcmp 越界(ASAN heap-buffer-overflow)。 修复:HandlesClassDef 与 DeclarationGenerator 的多继承展平改为递归按继承源去重(每类只展平一次,只取自有字段;同名字段如 TempDir 跨非继承 Mixin 仍各自保留,避免 2026-08-10 历史去重缺陷回归)。
This commit is contained in:
1 parent
2922af79f1
commit
81ad712475
2 files changed
+217
-111
No files matched your search
@@ -658,20 +658,55 @@ class ClassHandle(BaseHandle):
|
||||
# 字段重复——当前项目 Mixin 为兄弟无共享祖先;若未来出现真菱形需改为
|
||||
# "按继承源去重"而非"按字段名去重"。
|
||||
# ============================================================
|
||||
# 按继承源去重(2026-08-18):菱形继承(子类同时继承 A、B、D 且
|
||||
# A/B 也继承 D)会让 D 的字段被重复展平。典型:Generator 同时继承
|
||||
# ClassGenMixin/ClassGenEnum/ClassGenGeneric/ClassGenVTable/ClassGenDef/
|
||||
# ClassGenBase,而前 5 个都继承 ClassGenBase → ClassGenBase 41 字段
|
||||
# 被展平 6 次,struct 膨胀且 this_adjust/字段 GEP 全部错位。
|
||||
# 修复:递归展平整个继承树,每个类只处理一次;每类只贡献
|
||||
# "非祖先字段"(class_members[类] 是含祖先的展平结果,需剔除祖先
|
||||
# 部分)。同名字段(如 TempDir 在 CallGenBase/TypeGenBase 各自声明)
|
||||
# 因非继承关系,两个类都贡献,各自保留——符合下方 L654 注释的
|
||||
# "按继承源去重"而非"按字段名去重"。
|
||||
def _FlattenInherited(cls_name: str, _seen_cls: set,
|
||||
_out: list, _gen) -> None:
|
||||
if cls_name in _seen_cls:
|
||||
return
|
||||
_seen_cls.add(cls_name)
|
||||
for _gp in _gen.class_parents.get(cls_name, []) or []:
|
||||
_FlattenInherited(_gp, _seen_cls, _out, _gen)
|
||||
# 收集该类的全部祖先字段名(含间接),剔除自身已展平结果中
|
||||
# 属于祖先的部分(避免 class_members[类] 里混合的祖先字段重复)
|
||||
_anc_names: set[str] = set()
|
||||
_stack: list[str] = [cls_name]
|
||||
_vis: set[str] = set()
|
||||
while _stack:
|
||||
_c = _stack.pop()
|
||||
for _gp in _gen.class_parents.get(_c, []) or []:
|
||||
if _gp in _vis:
|
||||
continue
|
||||
_vis.add(_gp)
|
||||
_stack.append(_gp)
|
||||
for _mn, _mt in _gen.class_members.get(_gp, []) or []:
|
||||
_anc_names.add(_mn)
|
||||
for _mn, _mt in _gen.class_members.get(cls_name, []) or []:
|
||||
if _mn == '__vtable__':
|
||||
continue
|
||||
if _mn in _anc_names:
|
||||
continue
|
||||
_out.append((_mn, _mt))
|
||||
_pd: dict = dict(_gen.class_member_defaults.get(cls_name, {}))
|
||||
if _mn in _pd:
|
||||
_gen.class_member_defaults[ClassName][_mn] = _pd[_mn]
|
||||
|
||||
_seen_cls: set[str] = set()
|
||||
_flat: list[tuple] = []
|
||||
for ParentClass in ParentClasses:
|
||||
if ParentClass not in class_graph and ParentClass not in Gen.class_members:
|
||||
continue
|
||||
parent_members: list = list(Gen.class_members.get(ParentClass, []))
|
||||
parent_defaults: dict = dict(Gen.class_member_defaults.get(ParentClass, {}))
|
||||
inherited: list[tuple] = []
|
||||
for pm_name, pm_type in parent_members:
|
||||
if pm_name == '__vtable__':
|
||||
continue
|
||||
inherited.append((pm_name, pm_type))
|
||||
if pm_name in parent_defaults:
|
||||
Gen.class_member_defaults[ClassName][pm_name] = parent_defaults[pm_name]
|
||||
if inherited:
|
||||
Gen.class_members[ClassName] = Gen.class_members[ClassName] + inherited
|
||||
_FlattenInherited(ParentClass, _seen_cls, _flat, Gen)
|
||||
if _flat:
|
||||
Gen.class_members[ClassName] = Gen.class_members[ClassName] + _flat
|
||||
# ============================================================
|
||||
# 多继承方法合并:遍历所有父类(声明顺序)收集方法(短名去重,先声明父类优先),
|
||||
# vtable 槽/方法名用"实际定义类.方法"(如 B.get_b,与 TPV 一致),
|
||||
|
||||
Reference in new issue
Block a user