cython-devel

changeset 1870:478a5cfba350

Bug 158 -- raise error if cdef variable declared after it's used.
author Kurt Smith <kwsmith1@wisc.edu>
date Tue Mar 17 00:02:46 2009 -0500 (2 years ago)
parents 137b3d0a0c60
children e2365a6d00b8
files Cython/Compiler/ParseTreeTransforms.py tests/errors/declareafteruse_T158.pyx
line diff
1.1 --- a/Cython/Compiler/ParseTreeTransforms.py Mon Mar 16 21:33:46 2009 +0100 1.2 +++ b/Cython/Compiler/ParseTreeTransforms.py Tue Mar 17 00:02:46 2009 -0500 1.3 @@ -658,6 +658,8 @@ 1.4 rhs = decorator_result) 1.5 return [func_node, reassignment] 1.6 1.7 + 1.8 +ERR_DEC_AFTER = "cdef variable '%s' declared after it's used." 1.9 class AnalyseDeclarationsTransform(CythonTransform): 1.10 1.11 basic_property = TreeFragment(u""" 1.12 @@ -670,14 +672,23 @@ 1.13 1.14 def __call__(self, root): 1.15 self.env_stack = [root.scope] 1.16 + # needed to determine if a cdef var is declared after it's used. 1.17 + self.local_scope_stack = [] 1.18 return super(AnalyseDeclarationsTransform, self).__call__(root) 1.19 1.20 + def visit_NameNode(self, node): 1.21 + self.local_scope_stack[-1].add(node.name) 1.22 + return node 1.23 + 1.24 def visit_ModuleNode(self, node): 1.25 + self.local_scope_stack.append(set()) 1.26 node.analyse_declarations(self.env_stack[-1]) 1.27 self.visitchildren(node) 1.28 + self.local_scope_stack.pop() 1.29 return node 1.30 1.31 def visit_FuncDefNode(self, node): 1.32 + self.local_scope_stack.append(set()) 1.33 lenv = node.create_local_scope(self.env_stack[-1]) 1.34 node.body.analyse_control_flow(lenv) # this will be totally refactored 1.35 node.declare_arguments(lenv) 1.36 @@ -692,6 +703,7 @@ 1.37 self.env_stack.append(lenv) 1.38 self.visitchildren(node) 1.39 self.env_stack.pop() 1.40 + self.local_scope_stack.pop() 1.41 return node 1.42 1.43 # Some nodes are no longer needed after declaration 1.44 @@ -699,6 +711,8 @@ 1.45 # on these nodes in a seperate recursive process from the 1.46 # enclosing function or module, so we can simply drop them. 1.47 def visit_CDeclaratorNode(self, node): 1.48 + # necessary to ensure that all CNameDeclaratorNodes are visited. 1.49 + self.visitchildren(node) 1.50 return node 1.51 1.52 def visit_CTypeDefNode(self, node): 1.53 @@ -713,7 +727,18 @@ 1.54 def visit_CStructOrUnionDefNode(self, node): 1.55 return None 1.56 1.57 + def visit_CNameDeclaratorNode(self, node): 1.58 + if node.name in self.local_scope_stack[-1]: 1.59 + # cdef variable declared after it's used. 1.60 + error(node.pos, ERR_DEC_AFTER % node.name) 1.61 + self.visitchildren(node) 1.62 + return node 1.63 + 1.64 def visit_CVarDefNode(self, node): 1.65 + 1.66 + # to ensure all CNameDeclaratorNodes are visited. 1.67 + self.visitchildren(node) 1.68 + 1.69 if node.need_properties: 1.70 # cdef public attributes may need type testing on 1.71 # assignment, so we create a property accesss
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tests/errors/declareafteruse_T158.pyx Tue Mar 17 00:02:46 2009 -0500 2.3 @@ -0,0 +1,65 @@ 2.4 +def mult_decl_test(): 2.5 + print "%s" % vv 2.6 + print "%s" % s 2.7 + cdef str s, vv = "Test" 2.8 + 2.9 +def def_test(): 2.10 + cdef int j = 10 2.11 + i[0] = j 2.12 + cdef int *i = NULL # pointer variables are special case 2.13 + 2.14 +cdef cdef_test(): 2.15 + cdef int j = 10 2.16 + i[0] = j 2.17 + print "%d" % i[0] 2.18 + cdef int *i = NULL 2.19 + 2.20 +cpdef cpdef_test(): 2.21 + cdef int j = 10 2.22 + i[0] = j 2.23 + print "%d" % i[0] 2.24 + cdef int *i = NULL 2.25 + 2.26 +s.upper() 2.27 +cdef str s = "Test" 2.28 + 2.29 +class Foo(object): 2.30 + def bar(self, x, y): 2.31 + cdef unsigned long w = 20 2.32 + z = w + t 2.33 + cdef int t = 10 2.34 + 2.35 +cdef class Foo2(object): 2.36 + print '%s' % r # check error inside class scope 2.37 + cdef str r 2.38 + def bar(self, x, y): 2.39 + cdef unsigned long w = 20 2.40 + self.r = c'r' 2.41 + print self.r 2.42 + z = w + g(t) 2.43 + cdef int t = 10 2.44 + 2.45 +def g(x): 2.46 + return x 2.47 + 2.48 +cdef int d = 20 2.49 +baz[0] = d 2.50 +cdef int *baz 2.51 + 2.52 +print var[0][0] 2.53 +cdef unsigned long long var[100][100] 2.54 + 2.55 + 2.56 +_ERRORS = u""" 2.57 +4:13: cdef variable 's' declared after it's used. 2.58 +4:16: cdef variable 'vv' declared after it's used. 2.59 +9:14: cdef variable 'i' declared after it's used. 2.60 +15:14: cdef variable 'i' declared after it's used. 2.61 +21:14: cdef variable 'i' declared after it's used. 2.62 +24:9: cdef variable 's' declared after it's used. 2.63 +30:17: cdef variable 't' declared after it's used. 2.64 +34:13: cdef variable 'r' declared after it's used. 2.65 +40:17: cdef variable 't' declared after it's used. 2.66 +47:10: cdef variable 'baz' declared after it's used. 2.67 +50:24: cdef variable 'var' declared after it's used. 2.68 +"""