Add support for const pointers
authorVolker Mische <volker.mische@gmail.com>
Tue, 2 Apr 2013 17:08:26 +0000 (19:08 +0200)
committerVolker Mische <volker.mische@gmail.com>
Tue, 2 Apr 2013 17:08:26 +0000 (19:08 +0200)
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
tests/compile/const_decl.pyx
tests/errors/const_decl_errors.pyx

index 0634f40..f4b3852 100644 (file)
@@ -713,6 +713,19 @@ class CFuncDeclaratorNode(CDeclaratorNode):
         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.
     #
index ea1731b..dd665e2 100644 (file)
@@ -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
index fa293fb..5424c8f 100644 (file)
@@ -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)
index c04b1d2..48d7391 100644 (file)
@@ -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'
 """