class TypedExprNode(ExprNodes.ExprNode):
# Used for declaring assignments of a specified type without a known entry.
- def __init__(self, type, may_be_none=None):
+ def __init__(self, type, may_be_none=None, pos=None):
+ self.pos = pos
self.type = type
self._may_be_none = may_be_none
def is_tracked(self, entry):
if entry.is_anonymous:
return False
- if (entry.type.is_array or entry.type.is_struct_or_union or
- entry.type.is_cpp_class):
- return False
return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or
entry.from_closure or entry.in_closure or
entry.error_on_uninitialized)
+ def is_statically_assigned(self, entry):
+ if (entry.is_local and entry.is_variable and
+ (entry.type.is_struct_or_union or
+ entry.type.is_array or
+ entry.type.is_cpp_class)):
+ # stack allocated structured variable => never uninitialised
+ return True
+ return False
+
def mark_position(self, node):
"""Mark position, will be used to draw graph nodes."""
if self.block:
ret = set()
assmts = self.assmts[entry]
if istate & assmts.bit:
- if entry.from_closure:
+ if self.is_statically_assigned(entry):
+ ret.add(StaticAssignment(entry))
+ elif entry.from_closure:
ret.add(Unknown)
else:
ret.add(Uninitialized)
return self.rhs.type_dependencies(scope)
+class StaticAssignment(NameAssignment):
+ """Initialised at declaration time, e.g. stack allocation."""
+ def __init__(self, entry):
+ if not entry.type.is_pyobject:
+ may_be_none = False
+ else:
+ may_be_none = None # unknown
+ lhs = TypedExprNode(
+ entry.type, may_be_none=may_be_none, pos=entry.pos)
+ super(StaticAssignment, self).__init__(lhs, lhs, entry)
+
+ def infer_type(self, scope):
+ return self.entry.type
+
+ def type_dependencies(self, scope):
+ return []
+
+
class Argument(NameAssignment):
def __init__(self, lhs, rhs, entry):
NameAssignment.__init__(self, lhs, rhs, entry)
--- /dev/null
+# mode: run
+# tag: werror, control-flow
+# cython: warn.unused=True, warn.unused_arg=True, warn.unused_result=True
+
+cdef struct S:
+ int x
+ float y
+
+
+cdef stack_alloc_test(int[2] array_arg, S struct_arg):
+ cdef int[2] array_var
+ cdef S struct_var, struct_var_by_value
+
+ for i in range(2):
+ array_var[i] = array_arg[i]
+ struct_var.x, struct_var.y = struct_arg.x, struct_arg.y
+ struct_var_by_value = struct_var
+
+ return [ i for i in array_var ], struct_var_by_value
+
+
+def test():
+ """
+ >>> test()
+ ([0, 1], {'y': 2.0, 'x': 1})
+ """
+ cdef int[2] array_var
+ cdef S struct_var
+ for i in range(2):
+ array_var[i] = i
+ struct_var = [1, 2.0]
+
+ return stack_alloc_test(array_var, struct_var)