feat(tpc): 禁止类型联合 T1 | T2 并优化错误提示
四类类型注解入口统一调用 RejectTypeUnion:任意 T1 | T2 直接报错,报文含行号与 CPtr[T]/rawptr[T]、const/volatile/static/export/extern 替代写法;仅保留内建修饰标记与类型的组合。
This commit is contained in:
1 parent
f19d25782f
commit
3269775945
5 files changed
+54
-4
No files matched your search
@@ -10,7 +10,7 @@ import llvmlite.ir as ir
|
||||
from lib.core import TypeSystem
|
||||
from lib.core.TypeSystem import CTypeRegistry
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode,
|
||||
IsListAnnotation, AnnotationContainsName, RejectTypeUnion, IsCPtrSubscriptNode, IsCPtrNode,
|
||||
IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr,
|
||||
EnumClassIntWidth, ClassHasFuncLevelCVTable)
|
||||
|
||||
@@ -1187,6 +1187,8 @@ class DeclarationGenerator:
|
||||
if annotation is None:
|
||||
return 'i8*'
|
||||
|
||||
RejectTypeUnion(annotation)
|
||||
|
||||
non_struct_types: set[str] = {'list', 'dict', 'tuple', 'set', 'array', 'CArray', 'rawarray'}
|
||||
|
||||
if isinstance(annotation, ast.Name):
|
||||
|
||||
@@ -5,7 +5,7 @@ if TYPE_CHECKING:
|
||||
from typing import List
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode,
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, RejectTypeUnion,
|
||||
DesugarPtrSubscriptToUnion)
|
||||
from lib.core import TypeSystem
|
||||
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
|
||||
@@ -27,6 +27,7 @@ class HandlesTypeMerge(BaseHandle):
|
||||
|
||||
def GetCTypeInfo(self, Node: ast.AST) -> CTypeInfo:
|
||||
"""获取 CTypeInfo 对象"""
|
||||
RejectTypeUnion(Node)
|
||||
Result = self._GetCTypeInfoInternal(Node)
|
||||
if isinstance(Result, CTypeInfo):
|
||||
return Result
|
||||
|
||||
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, IsCPtrNode, IsCPtrSubscriptNode,
|
||||
IsListAnnotation, RejectTypeUnion, IsCPtrNode, IsCPtrSubscriptNode,
|
||||
IsRawPtrSubscriptNode, EnumIntWidth,
|
||||
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
|
||||
from lib.core import TypeSystem as _t
|
||||
@@ -121,6 +121,7 @@ class LLVMTypeMapper:
|
||||
if node is None:
|
||||
self._symtab.diagnostics.warn('', 0, "类型注解为 None,回退到 i32")
|
||||
return 'i32'
|
||||
RejectTypeUnion(node)
|
||||
if isinstance(node, ast.Name):
|
||||
return self._resolve_name(node)
|
||||
elif isinstance(node, ast.Attribute):
|
||||
|
||||
@@ -2160,6 +2160,51 @@ def RequireNameDefined(Gen: object, Trans: object, Node: object, Name: str) -> N
|
||||
)
|
||||
|
||||
|
||||
# 类型注解中允许出现在 `|` 一侧的内建修饰标记。除此之外的任何 `T1 | T2`
|
||||
# 都视为「类型联合」并直接拒绝:类型注解只能是单一类型。
|
||||
_UNION_MARKER_NAMES: frozenset[str] = frozenset({
|
||||
'CConst', 'CVolatile', 'CExport', 'CExtern', 'CStatic', 'CInline', 'State',
|
||||
'CDefine', 'CTypedef', 'CPtr', 'CArrayPtr', 'CAutoPtr', 'CRef', 'CTempRef',
|
||||
'BigEndian', 'LittleEndian', 'Bit',
|
||||
})
|
||||
|
||||
|
||||
def _IsUnionMarkerNode(node: ast.AST) -> bool:
|
||||
"""节点是否为内建修饰标记(裸名、attr.* 或带调用括号的标记)。"""
|
||||
if isinstance(node, ast.Name):
|
||||
return node.id in _UNION_MARKER_NAMES
|
||||
if isinstance(node, ast.Attribute):
|
||||
cur: ast.AST = node
|
||||
while isinstance(cur, ast.Attribute):
|
||||
cur = cur.value
|
||||
return isinstance(cur, ast.Name) and cur.id == 'attr'
|
||||
if isinstance(node, ast.Call):
|
||||
return _IsUnionMarkerNode(node.func)
|
||||
return False
|
||||
|
||||
|
||||
def _ContainsUnionMarker(node: ast.AST) -> bool:
|
||||
if _IsUnionMarkerNode(node):
|
||||
return True
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
return _ContainsUnionMarker(node.left) or _ContainsUnionMarker(node.right)
|
||||
return False
|
||||
|
||||
|
||||
def RejectTypeUnion(Annotation: ast.AST | None) -> None:
|
||||
"""拒绝 `T1 | T2` 类型联合;只允许「单一类型 | 内建修饰标记」。"""
|
||||
if not (isinstance(Annotation, ast.BinOp) and isinstance(Annotation.op, ast.BitOr)):
|
||||
return
|
||||
if _ContainsUnionMarker(Annotation):
|
||||
return
|
||||
Line: int = getattr(Annotation, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行)。"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T] / rawptr[T];"
|
||||
f"const / volatile / static / export / extern 请使用对应关键字。"
|
||||
)
|
||||
|
||||
|
||||
def AnnotationContainsMarker(node: ast.AST, MarkerName: str) -> bool:
|
||||
"""注解 AST 中是否出现指定内建标记名(裸名,或属性形态的尾名)。"""
|
||||
if isinstance(node, ast.Name):
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper
|
||||
from lib.core.ConstEvaluator import ConstEvaluator
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation,
|
||||
IsListAnnotation, RejectTypeUnion,
|
||||
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
|
||||
from lib.core import TypeSystem
|
||||
from lib.constants.config import mode as _config_mode
|
||||
@@ -91,6 +91,7 @@ class TypeAnnotationResolver:
|
||||
Node: AST 节点(如 ast.Name, ast.Attribute 等)
|
||||
SymbolTable: 符号表字典
|
||||
"""
|
||||
RejectTypeUnion(Node)
|
||||
if isinstance(Node, ast.Constant):
|
||||
return TypeAnnotationResolver._from_node_constant(Node, SymbolTable)
|
||||
if isinstance(Node, ast.Name):
|
||||
|
||||
Reference in new issue
Block a user