Skip to content

Commit

Permalink
Add support for const pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
vmx committed Apr 2, 2013
1 parent 7538ecd commit 5e14973
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
13 changes: 13 additions & 0 deletions Cython/Compiler/Nodes.py
Expand Up @@ -713,6 +713,19 @@ def declare_optional_arg_struct(self, func_type, env, fused_cname=None):
func_type.op_arg_struct = PyrexTypes.c_ptr_type(op_args_struct.type)


class CConstDeclaratorNode(CDeclaratorNode):
# base CDeclaratorNode

child_attrs = ["base"]

def analyse(self, base_type, env, nonempty = 0):
if base_type.is_pyobject:
error(self.pos,
"Const base type cannot be a Python object")
const = PyrexTypes.c_const_type(base_type)
return self.base.analyse(const, env, nonempty = nonempty)


class CArgDeclNode(Node):
# Item in a function declaration argument list.
#
Expand Down
16 changes: 13 additions & 3 deletions Cython/Compiler/Parsing.py
Expand Up @@ -2366,9 +2366,19 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
calling_convention = p_calling_convention(s)
if s.sy == '*':
s.next()
base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
cmethod_flag = cmethod_flag,
assignable = assignable, nonempty = nonempty)
if s.systring == 'const':
const_pos = s.position()
s.next()
const_base = p_c_declarator(s, ctx, empty = empty,
is_type = is_type,
cmethod_flag = cmethod_flag,
assignable = assignable,
nonempty = nonempty)
base = Nodes.CConstDeclaratorNode(const_pos, base = const_base)
else:
base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
cmethod_flag = cmethod_flag,
assignable = assignable, nonempty = nonempty)
result = Nodes.CPtrDeclaratorNode(pos,
base = base)
elif s.sy == '**': # scanner returns this as a single token
Expand Down
5 changes: 3 additions & 2 deletions tests/compile/const_decl.pyx
@@ -1,11 +1,12 @@
# mode: compile

cdef const_args(const int a, const int *b, const (int*) c):
cdef const_args(const int a, const int *b, const (int*) c, int *const d):
print a
print b[0]
b = NULL # OK, the pointer itself is not const
c[0] = 4 # OK, the value is not const
d[0] = 7 # OK, the value is not const

def call_const_args(x):
cdef int k = x
const_args(x, &k, &k)
const_args(x, &k, &k, &k)
15 changes: 10 additions & 5 deletions tests/errors/const_decl_errors.pyx
Expand Up @@ -10,17 +10,22 @@ cdef const int x = 10
cdef struct S:
int member

cdef func(const int a, const int* b, const (int*) c, const S s):
cdef func(const int a, const int* b, const (int*) c, const S s, int *const d,
const S *const t):
a = 10
c = NULL
b[0] = 100
s.member = 1000
d = NULL
t = &s

_ERRORS = """
3:5: Const base type cannot be a Python object
8:5: Assignment to const 'x'
14:6: Assignment to const 'a'
15:6: Assignment to const 'c'
16:5: Assignment to const dereference
17:5: Assignment to const attribute 'member'
15:6: Assignment to const 'a'
16:6: Assignment to const 'c'
17:5: Assignment to const dereference
18:5: Assignment to const attribute 'member'
19:6: Assignment to const 'd'
20:6: Assignment to const 't'
"""

0 comments on commit 5e14973

Please sign in to comment.