Commit cbc3ddcf authored by Mark Florisson's avatar Mark Florisson

Disallow private types in public or api cdef functions

parent 7bf54221
...@@ -1745,18 +1745,28 @@ class CFuncDefNode(FuncDefNode): ...@@ -1745,18 +1745,28 @@ class CFuncDefNode(FuncDefNode):
self.cfunc_declarator = declarator self.cfunc_declarator = declarator
self.args = declarator.args self.args = declarator.args
opt_arg_count = self.cfunc_declarator.optional_arg_count
if (self.visibility == 'public' or self.api) and opt_arg_count:
error(self.cfunc_declarator.pos,
"Function with optional arguments may not be declared "
"public or api")
for formal_arg, type_arg in zip(self.args, type.args): for formal_arg, type_arg in zip(self.args, type.args):
self.align_argument_type(env, type_arg) self.align_argument_type(env, type_arg)
formal_arg.type = type_arg.type formal_arg.type = type_arg.type
formal_arg.name = type_arg.name formal_arg.name = type_arg.name
formal_arg.cname = type_arg.cname formal_arg.cname = type_arg.cname
self._validate_type_visibility(type_arg.type, type_arg.pos, env)
if type_arg.type.is_fused: if type_arg.type.is_fused:
self.has_fused_arguments = True self.has_fused_arguments = True
if type_arg.type.is_buffer and 'inline' in self.modifiers: if type_arg.type.is_buffer and 'inline' in self.modifiers:
warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1) warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
self._validate_type_visibility(type.return_type, self.pos, env)
name = name_declarator.name name = name_declarator.name
cname = name_declarator.cname cname = name_declarator.cname
...@@ -1768,7 +1778,7 @@ class CFuncDefNode(FuncDefNode): ...@@ -1768,7 +1778,7 @@ class CFuncDefNode(FuncDefNode):
self.entry.inline_func_in_pxd = self.inline_in_pxd self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type self.return_type = type.return_type
if self.return_type.is_array and visibility != 'extern': if self.return_type.is_array and self.visibility != 'extern':
error(self.pos, error(self.pos,
"Function cannot return an array") "Function cannot return an array")
...@@ -1798,6 +1808,19 @@ class CFuncDefNode(FuncDefNode): ...@@ -1798,6 +1808,19 @@ class CFuncDefNode(FuncDefNode):
self.body = StatListNode(self.pos, stats=[self.override, self.body]) self.body = StatListNode(self.pos, stats=[self.override, self.body])
self.create_local_scope(env) self.create_local_scope(env)
def _validate_type_visibility(self, type, pos, env):
"""
Ensure that types used in cdef functions are public or api, or
defined in a C header.
"""
public_or_api = (self.visibility == 'public' or self.api)
entry = getattr(type, 'entry', None)
if public_or_api and entry and env.is_module_scope:
if not (entry.visibility in ('public', 'extern') or
entry.api or entry.in_cinclude):
error(pos, "Function declared public or api may not have "
"private types")
def call_self_node(self, omit_optional_args=0, is_module_scope=0): def call_self_node(self, omit_optional_args=0, is_module_scope=0):
import ExprNodes import ExprNodes
args = self.type.args args = self.type.args
......
...@@ -96,6 +96,7 @@ class PyrexType(BaseType): ...@@ -96,6 +96,7 @@ class PyrexType(BaseType):
# is_buffer boolean Is buffer access type # is_buffer boolean Is buffer access type
# has_attributes boolean Has C dot-selectable attributes # has_attributes boolean Has C dot-selectable attributes
# default_value string Initial value # default_value string Initial value
# entry Entry The Entry for this type
# #
# declaration_code(entity_code, # declaration_code(entity_code,
# for_display = 0, dll_linkage = None, pyrex = 0) # for_display = 0, dll_linkage = None, pyrex = 0)
......
...@@ -390,6 +390,9 @@ class Scope(object): ...@@ -390,6 +390,9 @@ class Scope(object):
entry.api = api entry.api = api
if defining: if defining:
self.type_entries.append(entry) self.type_entries.append(entry)
type.entry = entry
# here we would set as_variable to an object representing this type # here we would set as_variable to an object representing this type
return entry return entry
......
# mode: error
ctypedef char *string_t
ctypedef public char *public_string_t
ctypedef api char *api_string_t
# This should all fail
cdef public pub_func1(string_t x):
pass
cdef api api_func1(string_t x):
pass
cdef public string_t pub_func2():
pass
cdef api string_t api_func2():
pass
cdef public opt_pub_func(x = None):
pass
cdef api opt_api_func(x = None):
pass
# This should all work
cdef public pub_func3(public_string_t x, api_string_t y):
pass
cdef api api_func3(public_string_t x, api_string_t y):
pass
cdef opt_func(x = None):
pass
_ERRORS = u"""
e_public_cdef_private_types.pyx:8:22: Function declared public or api may not have private types
e_public_cdef_private_types.pyx:11:19: Function declared public or api may not have private types
e_public_cdef_private_types.pyx:14:5: Function declared public or api may not have private types
e_public_cdef_private_types.pyx:17:5: Function declared public or api may not have private types
e_public_cdef_private_types.pyx:20:25: Function with optional arguments may not be declared public or api
e_public_cdef_private_types.pyx:23:22: Function with optional arguments may not be declared public or api
"""
...@@ -9,6 +9,9 @@ ctypedef foo.bar(float) dtype2 ...@@ -9,6 +9,9 @@ ctypedef foo.bar(float) dtype2
ctypedef fused_type(foo) dtype3 ctypedef fused_type(foo) dtype3
dtype4 = cython.typedef(cython.fused_type(int, long, kw=None)) dtype4 = cython.typedef(cython.fused_type(int, long, kw=None))
ctypedef public cython.fused_type(int, long) dtype7
ctypedef api cython.fused_type(int, long) dtype8
# This is all valid # This is all valid
ctypedef fused_type(int, long, float) dtype5 ctypedef fused_type(int, long, float) dtype5
...@@ -19,4 +22,6 @@ fused_types.pyx:7:13: Can only fuse types with cython.fused_type() ...@@ -19,4 +22,6 @@ fused_types.pyx:7:13: Can only fuse types with cython.fused_type()
fused_types.pyx:8:17: Can only fuse types with cython.fused_type() fused_types.pyx:8:17: Can only fuse types with cython.fused_type()
fused_types.pyx:9:20: 'foo' is not a type identifier fused_types.pyx:9:20: 'foo' is not a type identifier
fused_types.pyx:10:23: fused_type does not take keyword arguments fused_types.pyx:10:23: fused_type does not take keyword arguments
fused_types.pyx:12:0: Fused types cannot be public or api
fused_types.pyx:13:0: Fused types cannot be public or api
""" """
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment