Commit cd4d9281 authored by Lisandro Dalcin's avatar Lisandro Dalcin

merge

parents 857606e7 aca194ad
......@@ -1553,9 +1553,9 @@ class IndexNode(ExprNode):
self.index.analyse_types(env, skip_children=skip_child_analysis)
elif not skip_child_analysis:
self.index.analyse_types(env)
self.original_index_type = self.index.type
if self.base.type.is_pyobject:
if self.index.type.is_int and not self.index.type.is_longlong:
self.original_index_type = self.index.type
self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
else:
self.index = self.index.coerce_to_pyobject(env)
......
......@@ -84,13 +84,13 @@ class Context:
from AutoDocTransforms import EmbedSignature
from Optimize import FlattenInListTransform, SwitchTransform, FinalOptimizePhase
from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_classes
from ModuleNode import check_c_declarations
if pxd:
_check_c_classes = None
_check_c_declarations = None
_specific_post_parse = PxdPostParse(self)
else:
_check_c_classes = check_c_classes
_check_c_declarations = check_c_declarations
_specific_post_parse = None
if py and not pxd:
......@@ -111,7 +111,7 @@ class Context:
EmbedSignature(self),
TransformBuiltinMethods(self),
IntroduceBufferAuxiliaryVars(self),
_check_c_classes,
_check_c_declarations,
AnalyseExpressionsTransform(self),
SwitchTransform(),
FinalOptimizePhase(self),
......
......@@ -26,8 +26,9 @@ from Cython.Utils import open_new_file, replace_suffix, UtilityCode
from StringEncoding import escape_byte_string, EncodedString
def check_c_classes(module_node):
def check_c_declarations(module_node):
module_node.scope.check_c_classes()
module_node.scope.check_c_functions()
return module_node
class ModuleNode(Nodes.Node, Nodes.BlockNode):
......
......@@ -1925,7 +1925,7 @@ class DefNode(FuncDefNode):
positional_args, kw_only_args, argtuple_error_label, code)
# --- optimised code when we do not receive any keyword arguments
if min_positional_args > 0 or min_positional_args == max_positional_args:
if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
# Python raises arg tuple related errors first, so we must
# check the length here
if min_positional_args == max_positional_args and not self.star_arg:
......@@ -1951,6 +1951,7 @@ class DefNode(FuncDefNode):
len(positional_args) + i))
code.putln(code.error_goto(self.pos))
break
elif min_positional_args == max_positional_args:
# parse the exact number of positional arguments from the
# args tuple
......@@ -1958,11 +1959,14 @@ class DefNode(FuncDefNode):
for i, arg in enumerate(positional_args):
item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
self.generate_arg_assignment(arg, item, code)
else:
# parse the positional arguments from the variable length
# args tuple
code.putln('} else {')
code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
if self.star_arg:
code.putln('default:')
reversed_args = list(enumerate(positional_args))[::-1]
for i, arg in reversed_args:
if i >= min_positional_args-1:
......@@ -1972,10 +1976,15 @@ class DefNode(FuncDefNode):
code.put('case %2d: ' % (i+1))
item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
self.generate_arg_assignment(arg, item, code)
if not self.star_arg:
if min_positional_args == 0:
code.put('case 0: ')
code.putln('break;')
if self.star_arg:
if min_positional_args:
for i in range(min_positional_args-1, -1, -1):
code.putln('case %2d:' % i)
code.put_goto(argtuple_error_label)
else:
code.put('default: ')
code.put_goto(argtuple_error_label)
code.putln('}')
......@@ -4683,11 +4692,11 @@ static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed
raise_argtuple_invalid_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
""",
impl = """
static INLINE void __Pyx_RaiseArgtupleInvalid(
static void __Pyx_RaiseArgtupleInvalid(
const char* func_name,
int exact,
Py_ssize_t num_min,
......@@ -4739,11 +4748,11 @@ static INLINE void __Pyx_RaiseKeywordRequired(
raise_double_keywords_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_RaiseDoubleKeywordsError(
static void __Pyx_RaiseDoubleKeywordsError(
const char* func_name, PyObject* kw_name); /*proto*/
""",
impl = """
static INLINE void __Pyx_RaiseDoubleKeywordsError(
static void __Pyx_RaiseDoubleKeywordsError(
const char* func_name,
PyObject* kw_name)
{
......
......@@ -1313,6 +1313,8 @@ def c_array_type(base_type, size):
# Construct a C array type.
if base_type is c_char_type:
return CCharArrayType(size)
elif base_type is error_type:
return error_type
else:
return CArrayType(base_type, size)
......@@ -1320,6 +1322,8 @@ def c_ptr_type(base_type):
# Construct a C pointer type.
if base_type is c_char_type:
return c_char_ptr_type
elif base_type is error_type:
return error_type
else:
return CPtrType(base_type)
......
......@@ -135,6 +135,7 @@ class Entry:
used = 0
is_special = 0
defined_in_pxd = 0
is_implemented = 0
api = 0
utility_code = None
is_overridable = 0
......@@ -445,6 +446,8 @@ class Scope:
entry.api = 1
if not defining and not in_pxd and visibility != 'extern':
error(pos, "Non-extern C function '%s' declared but not defined" % name)
if defining:
entry.is_implemented = True
return entry
def add_cfunction(self, name, type, pos, cname, visibility):
......@@ -1093,8 +1096,8 @@ class ModuleScope(Scope):
for entry in self.c_class_entries:
if debug_check_c_classes:
print("...entry %s %s" % (entry.name, entry))
print("......type = " + entry.type)
print("......visibility = " + entry.visibility)
print("......type = ", entry.type)
print("......visibility = ", entry.visibility)
type = entry.type
name = entry.name
visibility = entry.visibility
......@@ -1117,6 +1120,18 @@ class ModuleScope(Scope):
#print "ModuleScope.check_c_classes: allocating vtable cname for", self ###
type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name)
def check_c_functions(self):
# Performs post-analysis checking making sure all
# defined c functions are actually implemented.
for name, entry in self.entries.items():
if entry.is_cfunction:
if (entry.defined_in_pxd
and entry.scope is self
and entry.visibility != 'extern'
and not entry.in_cinclude
and not entry.is_implemented):
error(entry.pos, "Non-extern C function '%s' declared but not defined" % name)
def attach_var_entry_to_c_class(self, entry):
# The name of an extension class has to serve as both a type
# name and a variable name holding the type object. It is
......
......@@ -20,6 +20,9 @@ cdef f(Grail g, # incomplete argument type
int a[]):
pass
cdef NoSuchType* ptr
ptr = None # This should not produce another error
_ERRORS = u"""
3:19: Python object cannot be declared extern
4:16: Array element cannot be a Python object
......@@ -35,4 +38,5 @@ _ERRORS = u"""
19:1: Use spam() rather than spam(void) to declare a function with no arguments.
18:7: Argument type 'Grail' is incomplete
19:1: Invalid use of 'void'
23:5: 'NoSuchType' is not a type identifier
"""
......@@ -90,8 +90,48 @@ __doc__ = u"""
>>> test_int_kwargs(h)
Traceback (most recent call last):
TypeError: h() keywords must be strings
>>> d()
Traceback (most recent call last):
TypeError: d() takes at least 1 positional argument (0 given)
>>> d(1)
1 1 0 0
>>> d(1,2)
1 2 0 0
>>> d(1,2,3)
1 2 1 0
>>> d(key=None)
Traceback (most recent call last):
TypeError: d() takes at least 1 positional argument (0 given)
>>> d(1, key=None)
1 1 0 1
>>> d(1,2, key=None)
1 2 0 1
>>> d(1,2,3, key=None)
1 2 1 1
>>> c()
10 20 0
>>> c(1)
1 20 0
>>> c(1,2)
1 2 0
>>> c(key=None)
10 20 1
>>> c(1, key=None)
1 20 1
>>> c(1,2, key=None)
1 2 1
"""
def c(a=10, b=20, **kwds):
print a, b, len(kwds)
def d(a, b=1, *args, **kwds):
print a, b, len(args), len(kwds)
def e(*args, **kwargs):
print len(args), len(kwargs)
......@@ -112,7 +152,6 @@ if sys.version_info[0] >= 3:
else:
kwargs = {"test" : u"toast"}
def test_kw_args(f):
f(1,2, c=3)
f(1,2, d=3, *args)
......
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