Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
ec5a056e
Commit
ec5a056e
authored
Apr 10, 2017
by
Jeroen Demeyer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for "volatile" keyword
parent
4b64bbe1
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
158 additions
and
74 deletions
+158
-74
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+2
-2
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+4
-4
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+1
-1
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+5
-3
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+22
-7
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+76
-46
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+12
-8
Cython/Compiler/TypeInference.py
Cython/Compiler/TypeInference.py
+2
-2
tests/compile/volatile.pyx
tests/compile/volatile.pyx
+17
-0
tests/errors/const_decl_errors.pyx
tests/errors/const_decl_errors.pyx
+4
-1
tests/errors/duplicate_const.pyx
tests/errors/duplicate_const.pyx
+13
-0
No files found.
Cython/Compiler/Code.py
View file @
ec5a056e
...
...
@@ -822,8 +822,8 @@ class FunctionState(object):
A C string referring to the variable is returned.
"""
if type.is_c
onst
and not type.is_reference:
type = type.c
onst
_base_type
if type.is_c
v_qualified
and not type.is_reference:
type = type.c
v
_base_type
elif type.is_reference and not type.is_fake_reference:
type = type.ref_base_type
if not type.is_pyobject and not type.is_memoryviewslice:
...
...
Cython/Compiler/ExprNodes.py
View file @
ec5a056e
...
...
@@ -881,8 +881,8 @@ class ExprNode(Node):
if
used_as_reference
and
not
src_type
.
is_reference
:
dst_type
=
dst_type
.
ref_base_type
if
src_type
.
is_c
onst
:
src_type
=
src_type
.
c
onst
_base_type
if
src_type
.
is_c
v_qualified
:
src_type
=
src_type
.
c
v
_base_type
if
src_type
.
is_fused
or
dst_type
.
is_fused
:
# See if we are coercing a fused function to a pointer to a
...
...
@@ -2868,8 +2868,8 @@ class NextNode(AtomicExprNode):
item_type
=
env
.
lookup_operator_for_types
(
self
.
pos
,
"*"
,
[
iterator_type
]).
type
.
return_type
if
item_type
.
is_reference
:
item_type
=
item_type
.
ref_base_type
if
item_type
.
is_c
onst
:
item_type
=
item_type
.
c
onst
_base_type
if
item_type
.
is_c
v_qualified
:
item_type
=
item_type
.
c
v
_base_type
return
item_type
else
:
# Avoid duplication of complicated logic.
...
...
Cython/Compiler/MemoryView.py
View file @
ec5a056e
...
...
@@ -487,7 +487,7 @@ def copy_c_or_fortran_cname(memview):
def
get_copy_new_utility
(
pos
,
from_memview
,
to_memview
):
if
(
from_memview
.
dtype
!=
to_memview
.
dtype
and
not
(
from_memview
.
dtype
.
is_c
onst
and
from_memview
.
dtype
.
const
_base_type
==
to_memview
.
dtype
)):
not
(
from_memview
.
dtype
.
is_c
v_qualified
and
from_memview
.
dtype
.
cv
_base_type
==
to_memview
.
dtype
)):
error
(
pos
,
"dtypes must be the same!"
)
return
if
len
(
from_memview
.
axes
)
!=
len
(
to_memview
.
axes
):
...
...
Cython/Compiler/Nodes.py
View file @
ec5a056e
...
...
@@ -1273,8 +1273,10 @@ class FusedTypeNode(CBaseTypeNode):
return
PyrexTypes
.
FusedType
(
types
,
name
=
self
.
name
)
class
CConstTypeNode
(
CBaseTypeNode
):
class
CConst
OrVolatile
TypeNode
(
CBaseTypeNode
):
# base_type CBaseTypeNode
# is_const boolean
# is_volatile boolean
child_attrs
=
[
"base_type"
]
...
...
@@ -1282,8 +1284,8 @@ class CConstTypeNode(CBaseTypeNode):
base
=
self
.
base_type
.
analyse
(
env
,
could_be_name
)
if
base
.
is_pyobject
:
error
(
self
.
pos
,
"Const base type cannot be a Python object"
)
return
PyrexTypes
.
c_const_
type
(
bas
e
)
"Const
/volatile
base type cannot be a Python object"
)
return
PyrexTypes
.
c_const_
or_volatile_type
(
base
,
self
.
is_const
,
self
.
is_volatil
e
)
class
CVarDefNode
(
StatNode
):
...
...
Cython/Compiler/Parsing.py
View file @
ec5a056e
...
...
@@ -317,8 +317,8 @@ def p_typecast(s):
base_type
=
p_c_base_type
(
s
)
is_memslice
=
isinstance
(
base_type
,
Nodes
.
MemoryViewSliceTypeNode
)
is_template
=
isinstance
(
base_type
,
Nodes
.
TemplatedTypeNode
)
is_const
=
isinstance
(
base_type
,
Nodes
.
CConst
TypeNode
)
if
(
not
is_memslice
and
not
is_template
and
not
is_const
is_const
_volatile
=
isinstance
(
base_type
,
Nodes
.
CConstOrVolatile
TypeNode
)
if
(
not
is_memslice
and
not
is_template
and
not
is_const
_volatile
and
base_type
.
name
is
None
):
s
.
error
(
"Unknown type"
)
declarator
=
p_c_declarator
(
s
,
empty
=
1
)
...
...
@@ -2479,16 +2479,31 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
complex
=
0
module_path
=
[]
pos
=
s
.
position
()
if
not
s
.
sy
==
'IDENT'
:
error
(
pos
,
"Expected an identifier, found '%s'"
%
s
.
sy
)
# Handle const/volatile
is_const
=
is_volatile
=
0
while
True
:
if
s
.
systring
==
'const'
:
if
is_const
:
error
(
pos
,
"Duplicate 'const'"
)
is_const
=
1
elif
s
.
systring
==
'volatile'
:
if
is_volatile
:
error
(
pos
,
"Duplicate 'volatile'"
)
is_volatile
=
1
else
:
break
s
.
next
()
if
is_const
or
is_volatile
:
base_type
=
p_c_base_type
(
s
,
self_flag
=
self_flag
,
nonempty
=
nonempty
,
templates
=
templates
)
if
isinstance
(
base_type
,
Nodes
.
MemoryViewSliceTypeNode
):
# reverse order to avoid having to write "(const int)[:]"
base_type
.
base_type_node
=
Nodes
.
CConstTypeNode
(
pos
,
base_type
=
base_type
.
base_type_node
)
base_type
.
base_type_node
=
Nodes
.
CConstOrVolatileTypeNode
(
pos
,
base_type
=
base_type
.
base_type_node
,
is_const
=
is_const
,
is_volatile
=
is_volatile
)
return
base_type
return
Nodes
.
CConstTypeNode
(
pos
,
base_type
=
base_type
)
return
Nodes
.
CConstOrVolatileTypeNode
(
pos
,
base_type
=
base_type
,
is_const
=
is_const
,
is_volatile
=
is_volatile
)
if
s
.
sy
!=
'IDENT'
:
error
(
pos
,
"Expected an identifier, found '%s'"
%
s
.
sy
)
if
looking_at_base_type
(
s
):
#print "p_c_simple_base_type: looking_at_base_type at", s.position()
is_basic
=
1
...
...
Cython/Compiler/PyrexTypes.py
View file @
ec5a056e
...
...
@@ -176,7 +176,9 @@ class PyrexType(BaseType):
# is_ptr boolean Is a C pointer type
# is_null_ptr boolean Is the type of NULL
# is_reference boolean Is a C reference type
# is_const boolean Is a C const type.
# is_const boolean Is a C const type
# is_volatile boolean Is a C volatile type
# is_cv_qualified boolean Is a C const or volatile type
# is_cfunction boolean Is a C function type
# is_struct_or_union boolean Is a C struct or union type
# is_struct boolean Is a C struct type
...
...
@@ -236,6 +238,8 @@ class PyrexType(BaseType):
is_null_ptr
=
0
is_reference
=
0
is_const
=
0
is_volatile
=
0
is_cv_qualified
=
0
is_cfunction
=
0
is_struct_or_union
=
0
is_cpp_class
=
0
...
...
@@ -713,8 +717,8 @@ class MemoryViewSliceType(PyrexType):
to_axes_f
=
contig_dim
+
follow_dim
*
(
ndim
-
1
)
dtype
=
self
.
dtype
if
dtype
.
is_c
onst
:
dtype
=
dtype
.
c
onst
_base_type
if
dtype
.
is_c
v_qualified
:
dtype
=
dtype
.
c
v
_base_type
to_memview_c
=
MemoryViewSliceType
(
dtype
,
to_axes_c
)
to_memview_f
=
MemoryViewSliceType
(
dtype
,
to_axes_f
)
...
...
@@ -791,15 +795,18 @@ class MemoryViewSliceType(PyrexType):
# return False
src_dtype
,
dst_dtype
=
src
.
dtype
,
dst
.
dtype
if
dst_dtype
.
is_const
:
# Requesting read-only views is always ok => consider only the non-const base type.
dst_dtype
=
dst_dtype
.
const_base_type
if
src_dtype
.
is_const
:
# When assigning between read-only views, compare only the non-const base types.
src_dtype
=
src_dtype
.
const_base_type
elif
copying
and
src_dtype
.
is_const
:
# Copying by value => ignore const on source.
src_dtype
=
src_dtype
.
const_base_type
# We can add but not remove const/volatile modifiers
# (except if we are copying by value, then anything is fine)
if
not
copying
:
if
src_dtype
.
is_const
and
not
dst_dtype
.
is_const
:
return
False
if
src_dtype
.
is_volatile
and
not
dst_dtype
.
is_volatile
:
return
False
# const/volatile checks are done, remove those qualifiers
if
src_dtype
.
is_cv_qualified
:
src_dtype
=
src_dtype
.
cv_base_type
if
dst_dtype
.
is_cv_qualified
:
dst_dtype
=
dst_dtype
.
cv_base_type
if
src_dtype
!=
dst_dtype
:
return
False
...
...
@@ -1558,58 +1565,74 @@ class PythranExpr(CType):
return
hash
(
self
.
pythran_type
)
class
CConstType
(
BaseType
):
class
CConstOrVolatileType
(
BaseType
):
"A C const or volatile type"
is_c
onst
=
1
is_c
v_qualified
=
1
def
__init__
(
self
,
const_base_type
):
self
.
const_base_type
=
const_base_type
if
const_base_type
.
has_attributes
and
const_base_type
.
scope
is
not
None
:
from
.
import
Symtab
self
.
scope
=
Symtab
.
CConstScope
(
const_base_type
.
scope
)
def
__init__
(
self
,
base_type
,
is_const
=
0
,
is_volatile
=
0
):
self
.
cv_base_type
=
base_type
self
.
is_const
=
is_const
self
.
is_volatile
=
is_volatile
if
base_type
.
has_attributes
and
base_type
.
scope
is
not
None
:
from
.Symtab
import
CConstOrVolatileScope
self
.
scope
=
CConstOrVolatileScope
(
base_type
.
scope
,
is_const
,
is_volatile
)
def
cv_string
(
self
):
cvstring
=
""
if
self
.
is_const
:
cvstring
=
"const "
+
cvstring
if
self
.
is_volatile
:
cvstring
=
"volatile "
+
cvstring
return
cvstring
def
__repr__
(
self
):
return
"<CConst
Type %s>"
%
repr
(
self
.
const
_base_type
)
return
"<CConst
OrVolatileType %s%r>"
%
(
self
.
cv_string
(),
self
.
cv
_base_type
)
def
__str__
(
self
):
return
self
.
declaration_code
(
""
,
for_display
=
1
)
def
declaration_code
(
self
,
entity_code
,
for_display
=
0
,
dll_linkage
=
None
,
pyrex
=
0
):
cv
=
self
.
cv_string
()
if
for_display
or
pyrex
:
return
"const "
+
self
.
const
_base_type
.
declaration_code
(
entity_code
,
for_display
,
dll_linkage
,
pyrex
)
return
cv
+
self
.
cv
_base_type
.
declaration_code
(
entity_code
,
for_display
,
dll_linkage
,
pyrex
)
else
:
return
self
.
c
onst_base_type
.
declaration_code
(
"const %s"
%
entity_code
,
for_display
,
dll_linkage
,
pyrex
)
return
self
.
c
v_base_type
.
declaration_code
(
cv
+
entity_code
,
for_display
,
dll_linkage
,
pyrex
)
def
specialize
(
self
,
values
):
base_type
=
self
.
c
onst
_base_type
.
specialize
(
values
)
if
base_type
==
self
.
c
onst
_base_type
:
base_type
=
self
.
c
v
_base_type
.
specialize
(
values
)
if
base_type
==
self
.
c
v
_base_type
:
return
self
else
:
return
CConstType
(
base_typ
e
)
return
CConstOrVolatileType
(
base_type
,
self
.
is_const
,
self
.
is_volatil
e
)
def
deduce_template_params
(
self
,
actual
):
return
self
.
c
onst
_base_type
.
deduce_template_params
(
actual
)
return
self
.
c
v
_base_type
.
deduce_template_params
(
actual
)
def
can_coerce_to_pyobject
(
self
,
env
):
return
self
.
c
onst
_base_type
.
can_coerce_to_pyobject
(
env
)
return
self
.
c
v
_base_type
.
can_coerce_to_pyobject
(
env
)
def
can_coerce_from_pyobject
(
self
,
env
):
return
self
.
c
onst
_base_type
.
can_coerce_from_pyobject
(
env
)
return
self
.
c
v
_base_type
.
can_coerce_from_pyobject
(
env
)
def
create_to_py_utility_code
(
self
,
env
):
if
self
.
c
onst
_base_type
.
create_to_py_utility_code
(
env
):
self
.
to_py_function
=
self
.
c
onst
_base_type
.
to_py_function
if
self
.
c
v
_base_type
.
create_to_py_utility_code
(
env
):
self
.
to_py_function
=
self
.
c
v
_base_type
.
to_py_function
return
True
def
same_as_resolved_type
(
self
,
other_type
):
if
other_type
.
is_c
onst
:
return
self
.
c
onst_base_type
.
same_as_resolved_type
(
other_type
.
const
_base_type
)
# Accept c
onst LHS <- non-const
RHS.
return
self
.
c
onst
_base_type
.
same_as_resolved_type
(
other_type
)
if
other_type
.
is_c
v_qualified
:
return
self
.
c
v_base_type
.
same_as_resolved_type
(
other_type
.
cv
_base_type
)
# Accept c
v LHS <- non-cv
RHS.
return
self
.
c
v
_base_type
.
same_as_resolved_type
(
other_type
)
def
__getattr__
(
self
,
name
):
return
getattr
(
self
.
const_base_type
,
name
)
return
getattr
(
self
.
cv_base_type
,
name
)
def
CConstType
(
base_type
):
return
CConstOrVolatileType
(
base_type
,
is_const
=
1
)
class
FusedType
(
CType
):
...
...
@@ -2302,8 +2325,8 @@ class CPointerBaseType(CType):
def
__init__
(
self
,
base_type
):
self
.
base_type
=
base_type
if
base_type
.
is_c
onst
:
base_type
=
base_type
.
c
onst
_base_type
if
base_type
.
is_c
v_qualified
:
base_type
=
base_type
.
c
v
_base_type
for
char_type
in
(
c_char_type
,
c_uchar_type
,
c_schar_type
):
if
base_type
.
same_as
(
char_type
):
self
.
is_string
=
1
...
...
@@ -2527,8 +2550,8 @@ class CPtrType(CPointerBaseType):
return
1
if
other_type
.
is_null_ptr
:
return
1
if
self
.
base_type
.
is_c
onst
:
self
=
CPtrType
(
self
.
base_type
.
c
onst
_base_type
)
if
self
.
base_type
.
is_c
v_qualified
:
self
=
CPtrType
(
self
.
base_type
.
c
v
_base_type
)
if
self
.
base_type
.
is_cfunction
:
if
other_type
.
is_ptr
:
other_type
=
other_type
.
base_type
.
resolve
()
...
...
@@ -3709,8 +3732,8 @@ class CppClassType(CType):
return
specialized
def
deduce_template_params
(
self
,
actual
):
if
actual
.
is_c
onst
:
actual
=
actual
.
c
onst
_base_type
if
actual
.
is_c
v_qualified
:
actual
=
actual
.
c
v
_base_type
if
actual
.
is_reference
:
actual
=
actual
.
ref_base_type
if
self
==
actual
:
...
...
@@ -4452,10 +4475,10 @@ def widest_numeric_type(type1, type2):
type1
=
type1
.
ref_base_type
if
type2
.
is_reference
:
type2
=
type2
.
ref_base_type
if
type1
.
is_c
onst
:
type1
=
type1
.
c
onst
_base_type
if
type2
.
is_c
onst
:
type2
=
type2
.
c
onst
_base_type
if
type1
.
is_c
v_qualified
:
type1
=
type1
.
c
v
_base_type
if
type2
.
is_c
v_qualified
:
type2
=
type2
.
c
v
_base_type
if
type1
==
type2
:
widest_type
=
type1
elif
type1
.
is_complex
or
type2
.
is_complex
:
...
...
@@ -4675,6 +4698,13 @@ def c_const_type(base_type):
else
:
return
CConstType
(
base_type
)
def
c_const_or_volatile_type
(
base_type
,
is_const
,
is_volatile
):
# Construct a C const/volatile type.
if
base_type
is
error_type
:
return
error_type
else
:
return
CConstOrVolatileType
(
base_type
,
is_const
,
is_volatile
)
def
same_type
(
type1
,
type2
):
return
type1
.
same_as
(
type2
)
...
...
Cython/Compiler/Symtab.py
View file @
ec5a056e
...
...
@@ -2523,23 +2523,27 @@ class PropertyScope(Scope):
return
None
class
CConstScope
(
Scope
):
class
CConst
OrVolatile
Scope
(
Scope
):
def
__init__
(
self
,
const_base_type_scope
):
def
__init__
(
self
,
base_type_scope
,
is_const
=
0
,
is_volatile
=
0
):
Scope
.
__init__
(
self
,
'const_'
+
const_base_type_scope
.
name
,
const_base_type_scope
.
outer_scope
,
const_base_type_scope
.
parent_scope
)
self
.
const_base_type_scope
=
const_base_type_scope
'cv_'
+
base_type_scope
.
name
,
base_type_scope
.
outer_scope
,
base_type_scope
.
parent_scope
)
self
.
base_type_scope
=
base_type_scope
self
.
is_const
=
is_const
self
.
is_volatile
=
is_volatile
def
lookup_here
(
self
,
name
):
entry
=
self
.
const_
base_type_scope
.
lookup_here
(
name
)
entry
=
self
.
base_type_scope
.
lookup_here
(
name
)
if
entry
is
not
None
:
entry
=
copy
.
copy
(
entry
)
entry
.
type
=
PyrexTypes
.
c_const_type
(
entry
.
type
)
entry
.
type
=
PyrexTypes
.
c_const_or_volatile_type
(
entry
.
type
,
self
.
is_const
,
self
.
is_volatile
)
return
entry
class
TemplateScope
(
Scope
):
def
__init__
(
self
,
name
,
outer_scope
):
Scope
.
__init__
(
self
,
name
,
outer_scope
,
None
)
...
...
Cython/Compiler/TypeInference.py
View file @
ec5a056e
...
...
@@ -533,8 +533,8 @@ def find_spanning_type(type1, type2):
def
simply_type
(
result_type
,
pos
):
if
result_type
.
is_reference
:
result_type
=
result_type
.
ref_base_type
if
result_type
.
is_c
onst
:
result_type
=
result_type
.
c
onst
_base_type
if
result_type
.
is_c
v_qualified
:
result_type
=
result_type
.
c
v
_base_type
if
result_type
.
is_cpp_class
:
result_type
.
check_nullary_constructor
(
pos
)
if
result_type
.
is_array
:
...
...
tests/compile/volatile.pyx
0 → 100644
View file @
ec5a056e
# mode: compile
cdef
volatile
int
x
=
1
cdef
const
volatile
char
*
greeting1
=
"hello world"
cdef
volatile
const
char
*
greeting2
=
"goodbye"
cdef
extern
from
"stdlib.h"
:
volatile
void
*
malloc
(
size_t
)
cdef
volatile
long
*
test
(
volatile
size_t
s
):
cdef
volatile
long
*
arr
=
<
long
*><
volatile
long
*>
malloc
(
s
)
return
arr
test
(
64
)
tests/errors/const_decl_errors.pyx
View file @
ec5a056e
...
...
@@ -19,9 +19,11 @@ cdef func(const int a, const int* b, const (int*) c, const S s, int *const d,
d
=
NULL
t
=
&
s
cdef
volatile
object
v
_ERRORS
=
"""
3:5: Const base type cannot be a Python object
3:5: Const
/volatile
base type cannot be a Python object
8:5: Assignment to const 'x'
15:4: Assignment to const 'a'
16:4: Assignment to const 'c'
...
...
@@ -29,4 +31,5 @@ _ERRORS = """
18:5: Assignment to const attribute 'member'
19:4: Assignment to const 'd'
20:4: Assignment to const 't'
22:5: Const/volatile base type cannot be a Python object
"""
tests/errors/duplicate_const.pyx
0 → 100644
View file @
ec5a056e
# mode: error
cdef
extern
from
*
:
cdef
const
const
int
a
cdef
const
volatile
int
b
cdef
volatile
const
int
c
cdef
volatile
volatile
int
d
_ERRORS
=
"""
4:9: Duplicate 'const'
7:9: Duplicate 'volatile'
"""
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment