fix(codegen): widen method calls by the declared return signedness

This commit is contained in:
TermiNexus committed 2026-10-27 19:56:56 +08:00
1 parent 7cbe4e93dc
commit 002a98f3f4
1 file changed
+29 -2
+29 -2
View File
@@ -203,6 +203,29 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
elif w_cd == 32:
if v_cd > 2147483647: return 1
return 0
def _attr_call_ret_entry(self, pool: memhub.MemBuddy*, at: ast.Attribute*, trans: HT.Translator*) -> GenTypes.FuncEntry*:
"""FuncEntry for a `recv.attr(...)` call (method or module-qualified free function), else None."""
if at is None or at.attr is None or trans is None: return None
# Module-qualified free function: `import mod` then mod.f().
if at.value is not None and at.value.kind() == ast.ASTKind.Name and trans._imported_modules is not None:
rn: ast.Name* = ast.Name*(at.value)
if rn.id is not None:
if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, rn.id) != 0:
fe_mod: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(at.attr)
if fe_mod is not None: return fe_mod
# Method: the receiver's class name gives the table key "Class.method".
if at.value is None: return None
cls: str = self._attr_receiver_class_name(pool, at.value, trans)
if cls is None: return None
bare: str = cls
dot: str = self.Gen.StructGen._last_dot_outside_brackets(cls)
if dot is not None: bare = dot + 1
n: sizet = string.strlen(bare) + string.strlen(at.attr) + 2
lu: str = pool.alloc(n)
if lu is None: return None
viperlib.snprintf(lu, n, "%s.%s", bare, at.attr)
return self.Gen.CallGenLeafKit.find_func_entry_global(lu)
def _node_type_unsigned(self, pool: memhub.MemBuddy*, node: ast.AST*, trans: HT.Translator* = None) -> int:
"""Return 1 if the AST node resolves to an unsigned integer type, else 0."""
if node is None: return 0
@@ -234,9 +257,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
if fe_fn_u.RetSign == GenTypes.FUNC_RET_SIGN_UNSIGNED: return 1
if fe_fn_u.Spec is not None and TSpec.SpecIsUnsigned(fe_fn_u.Spec.Ret) != 0: return 1
elif fk_u == ast.ASTKind.Attribute:
# Qualified type cast: t.CUInt16T(x) / mod.ULONG(x).
# Qualified type cast: t.CUInt16T(x); then method / module-qualified calls.
at_u: ast.Attribute* = ast.Attribute*(cl.func)
if at_u.attr is not None and self._type_name_unsigned(at_u.attr) != 0: return 1
fe_at_u: GenTypes.FuncEntry* = self._attr_call_ret_entry(pool, at_u, trans)
if fe_at_u is not None and fe_at_u.RetSign == GenTypes.FUNC_RET_SIGN_UNSIGNED: return 1
return 0
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
@@ -391,10 +416,12 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
fe_fn_s: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(nm_c.id)
if fe_fn_s is not None and fe_fn_s.RetSign == GenTypes.FUNC_RET_SIGN_SIGNED: return 1
elif fk_s == ast.ASTKind.Attribute:
# Qualified signed cast: t.CInt16T(x) / mod.LONG(x).
# Qualified signed cast (t.CInt16T(x)) or method / module-qualified call.
at_c: ast.Attribute* = ast.Attribute*(cl.func)
if at_c.attr is not None:
if self._spec_sign_from_annot(at_c.attr) == TSpec.TS_SIGN_SIGNED: return 1
fe_at_c: GenTypes.FuncEntry* = self._attr_call_ret_entry(pool, at_c, trans)
if fe_at_c is not None and fe_at_c.RetSign == GenTypes.FUNC_RET_SIGN_SIGNED: return 1
return 0
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)