diff --git a/packages/vipeye-internal/src/analyzer/checker.ts b/packages/vipeye-internal/src/analyzer/checker.ts index 4cb4a0a..f5e016a 100644 --- a/packages/vipeye-internal/src/analyzer/checker.ts +++ b/packages/vipeye-internal/src/analyzer/checker.ts @@ -7288,20 +7288,25 @@ export class Checker extends ParseTreeWalker { if (methodName === '__new__') { // __new__ overrides should have a "cls" parameter. - if (node.d.params.length === 0 || !node.d.params[0].d.name) { - this._evaluator.addDiagnostic( - DiagnosticRule.reportSelfClsParameterName, - LocMessage.newClsParam(), - node.d.name - ); - } else { - const paramName = node.d.params[0].d.name.d.value; - if (!clsNames.includes(paramName) && !(isMetaclass && clsNamesMetaclass.includes(paramName))) { + // Viper 扩展:Viper 中 `__new__` 的第一个参数就是 self(栈位置, + // 如 `_list.vp` 的 `def __new__(self, pool, elem_size=0)`), + // 与 Python 的 cls 语义不同,跳过参数名校验。 + if (!IsViperDialect(this._fileInfo.executionEnvironment.dialect)) { + if (node.d.params.length === 0 || !node.d.params[0].d.name) { this._evaluator.addDiagnostic( DiagnosticRule.reportSelfClsParameterName, LocMessage.newClsParam(), - node.d.params[0] + node.d.name ); + } else { + const paramName = node.d.params[0].d.name.d.value; + if (!clsNames.includes(paramName) && !(isMetaclass && clsNamesMetaclass.includes(paramName))) { + this._evaluator.addDiagnostic( + DiagnosticRule.reportSelfClsParameterName, + LocMessage.newClsParam(), + node.d.params[0] + ); + } } } diff --git a/packages/vipeye-internal/src/analyzer/constructors.ts b/packages/vipeye-internal/src/analyzer/constructors.ts index 8a8ce25..0b2ddf6 100644 --- a/packages/vipeye-internal/src/analyzer/constructors.ts +++ b/packages/vipeye-internal/src/analyzer/constructors.ts @@ -35,6 +35,7 @@ import { isAny, isClass, isClassInstance, + isCPtrType, isFunction, isFunctionOrOverloaded, isInstantiableClass, @@ -340,6 +341,19 @@ function validateNewAndInitMethods( initMethodBindToType = ClassType.cloneAsInstance(type); } + // Viper 扩展:`__new__` 返回 CPtr[...](裸指针分配语义)时, + // `__init__` 应绑定到类实例而非 CPtr(CPtr 上没有 `__init__` 方法)。 + // 这样 `list[str](pool)` 的构造调用结果保持类实例 `list[str]`。 + let isNewReturnPtr = false; + doForEachSubtype(newMethodReturnType, (subtype) => { + if (isCPtrType(subtype)) { + isNewReturnPtr = true; + } + }); + if (isNewReturnPtr) { + initMethodBindToType = ClassType.cloneAsInstance(type); + } + // Determine whether the class overrides the object.__init__ method. const initMethodDiag = new DiagnosticAddendum(); initMethodTypeResult = getBoundInitMethod(evaluator, errorNode, initMethodBindToType, initMethodDiag); @@ -1077,6 +1091,22 @@ function shouldSkipNewAndInitEvaluation( function shouldSkipInitEvaluation(evaluator: TypeEvaluator, classType: ClassType, newMethodReturnType: Type): boolean { const returnType = evaluator.makeTopLevelTypeVarsConcrete(newMethodReturnType); + // Viper 扩展:`__new__` 返回 CPtr[...](裸指针)时不跳过 `__init__` 验证。 + // Viper 中 `__new__` 负责分配内存并返回裸指针(如 `_list.vp` 的 + // `def __new__(self, pool, elem_size=0): return pool.alloc(48)`,返回 + // `t.CVoid | t.CPtr`),但构造调用 `list[str](pool)` 的结果仍是类实例 + // `list[str]`(由 `__init__` 的 self 类型确定)。CPtr 是 Viper 特有指针类型, + // 检测到 CPtr 返回即视为 Viper 分配语义,不应跳过 `__init__`。 + let isViperPtrAlloc = false; + doForEachSubtype(returnType, (subtype) => { + if (isCPtrType(subtype)) { + isViperPtrAlloc = true; + } + }); + if (isViperPtrAlloc) { + return false; + } + let skipInitCheck = false; doForEachSubtype(returnType, (subtype) => { if (isUnknown(subtype)) { diff --git a/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi b/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi index 0ffbe1c..5bb95b5 100644 --- a/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi +++ b/packages/vipeye-internal/vipershed-fallback/stdlib/c.vpi @@ -27,12 +27,13 @@ def Set(target: Any, value: T) -> None: """target = value。""" ... -def Asm(asm: str, *args: Any, op: Any = None) -> Any: - """内联汇编。op 为破坏描述符列表。""" +def Asm(asm: str, *args: Any, inp: Any = None, out: Any = None, op: Any = None) -> Any: + """内联汇编。inp 为输入操作数描述符列表,out 为输出操作数描述符列表, + op 为破坏描述符列表。""" ... -def LLVMIR(ir: str, *args: Any, op: Any = None) -> Any: - """LLVM IR 内联。op 为破坏描述符列表。""" +def LLVMIR(ir: str, *args: Any, inp: Any = None, out: Any = None, op: Any = None) -> Any: + """LLVM IR 内联。inp/out/op 为操作数描述符列表。""" ... def LInp(expr: Any, constraint: Any = None) -> Any: