Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d7a2258

Browse files
committed
Merge branch 'bugs'
Conflicts: Cython/Compiler/Optimize.py Cython/Compiler/TypeInference.py
2 parents a7707eb + 15dce27 commit d7a2258

14 files changed

Lines changed: 135 additions & 26 deletions

File tree

CHANGES.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ Bugs fixed
2525

2626
* C++ class nesting was broken.
2727

28+
* Better checking for required nullary constructors for stack-allocated C++ instances.
29+
30+
* Remove module docstring in no-docstring mode.
31+
32+
* Fix specialization for varargs function signatures.
33+
34+
* Fix several compiler crashes.
35+
2836
Other changes
2937
-------------
3038

Cython/Compiler/FusedNode.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def specialize_copied_def(self, node, cname, py_entry, f2s, fused_types):
211211
for fused_type in fused_types
212212
]
213213

214-
node.specialized_signature_string = ', '.join(type_strings)
214+
node.specialized_signature_string = '|'.join(type_strings)
215215

216216
node.entry.pymethdef_cname = PyrexTypes.get_fused_cname(
217217
cname, node.entry.pymethdef_cname)
@@ -322,7 +322,8 @@ def _buffer_check_numpy_dtype(self, pyx_code, specialized_buffer_types):
322322

323323
for dtype_category, codewriter in dtypes:
324324
if dtype_category:
325-
cond = '{{itemsize_match}}'
325+
cond = '{{itemsize_match}} and arg.ndim == %d' % (
326+
specialized_type.ndim,)
326327
if dtype.is_int:
327328
cond += ' and {{signed_match}}'
328329

@@ -587,7 +588,7 @@ def __pyx_fused_cpdef(signatures, args, kwargs, defaults):
587588
candidates = []
588589
for sig in signatures:
589590
match_found = False
590-
for src_type, dst_type in zip(sig.strip('()').split(', '), dest_sig):
591+
for src_type, dst_type in zip(sig.strip('()').split('|'), dest_sig):
591592
if dst_type is not None:
592593
if src_type == dst_type:
593594
match_found = True

Cython/Compiler/ModuleNode.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ def extend_if_not_in(L1, L2):
8686
self.scope.merge_in(scope)
8787

8888
def analyse_declarations(self, env):
89-
if Options.embed_pos_in_docstring:
89+
if not Options.docstrings:
90+
env.doc = self.doc = None
91+
elif Options.embed_pos_in_docstring:
9092
env.doc = EncodedString(u'File: %s (starting at line %s)' % Nodes.relative_position(self.pos))
9193
if not self.doc is None:
9294
env.doc = EncodedString(env.doc + u'\n' + self.doc)

Cython/Compiler/Nodes.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,12 @@ def analyse_declarations(self, env):
12391239
scope = None
12401240
if self.attributes is not None:
12411241
scope = CppClassScope(self.name, env, templates = self.templates)
1242-
base_class_types = [b.analyse(scope or env) for b in self.base_classes]
1242+
def base_ok(base_class):
1243+
if base_class.is_cpp_class or base_class.is_struct:
1244+
return True
1245+
else:
1246+
error(self.pos, "Base class '%s' not a struct or class." % base_class)
1247+
base_class_types = filter(base_ok, [b.analyse(scope or env) for b in self.base_classes])
12431248
if self.templates is None:
12441249
template_types = None
12451250
else:
@@ -2084,6 +2089,8 @@ def analyse_declarations(self, env):
20842089
if self.return_type.is_array and self.visibility != 'extern':
20852090
error(self.pos,
20862091
"Function cannot return an array")
2092+
if self.return_type.is_cpp_class:
2093+
self.return_type.check_nullary_constructor(self.pos, "used as a return value")
20872094

20882095
if self.overridable and not env.is_module_scope:
20892096
if len(self.args) < 1 or not self.args[0].type.is_pyobject:

Cython/Compiler/PyrexTypes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,6 +3314,11 @@ def find_cpp_operation_type(self, operator, operand_type=None):
33143314
func_type = func_type.base_type
33153315
return func_type.return_type
33163316

3317+
def check_nullary_constructor(self, pos, msg="stack allocated"):
3318+
constructor = self.scope.lookup(u'<init>')
3319+
if constructor is not None and best_match([], constructor.all_alternatives()) is None:
3320+
error(pos, "C++ class must have a nullary constructor to be %s" % msg)
3321+
33173322

33183323
class TemplatePlaceholderType(CType):
33193324

Cython/Compiler/Symtab.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -570,9 +570,7 @@ def declare_var(self, name, type, pos,
570570
else:
571571
cname = self.mangle(Naming.var_prefix, name)
572572
if type.is_cpp_class and visibility != 'extern':
573-
constructor = type.scope.lookup(u'<init>')
574-
if constructor is not None and PyrexTypes.best_match([], constructor.all_alternatives()) is None:
575-
error(pos, "C++ class must have a no-arg constructor to be stack allocated")
573+
type.check_nullary_constructor(pos)
576574
entry = self.declare(name, cname, type, pos, visibility)
577575
entry.is_variable = 1
578576
if in_pxd and visibility != 'extern':
@@ -1783,10 +1781,7 @@ def declare_var(self, name, type, pos,
17831781
if visibility == 'private':
17841782
cname = c_safe_identifier(cname)
17851783
if type.is_cpp_class and visibility != 'extern':
1786-
constructor = type.scope.lookup(u'<init>')
1787-
if constructor is not None and \
1788-
PyrexTypes.best_match([], constructor.all_alternatives()) is None:
1789-
error(pos, "C++ class must have a no-arg constructor to be a member of an extension type; use a pointer instead")
1784+
type.check_nullary_constructor(pos)
17901785
self.use_utility_code(Code.UtilityCode("#include <new>"))
17911786
entry = self.declare(name, cname, type, pos, visibility)
17921787
entry.is_variable = 1

Cython/Compiler/TypeInference.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ def resolve_dependancy(dep):
390390
types = [assmt.rhs.infer_type(scope)
391391
for assmt in entry.cf_assignments]
392392
if types and Utils.all(types):
393-
entry.type = spanning_type(types, entry.might_overflow)
393+
entry.type = spanning_type(types, entry.might_overflow, entry.pos)
394394
else:
395395
# FIXME: raise a warning?
396396
# print "No assignments", entry.pos, entry
@@ -405,10 +405,10 @@ def resolve_dependancy(dep):
405405
for assmt in entry.cf_assignments
406406
if assmt.type_dependencies(scope) == ()]
407407
if types:
408-
entry.type = spanning_type(types, entry.might_overflow)
408+
entry.type = spanning_type(types, entry.might_overflow, entry.pos)
409409
types = [assmt.infer_type(scope)
410410
for assmt in entry.cf_assignments]
411-
entry.type = spanning_type(types, entry.might_overflow) # might be wider...
411+
entry.type = spanning_type(types, entry.might_overflow, entry.pos) # might be wider...
412412
resolve_dependancy(entry)
413413
del dependancies_by_entry[entry]
414414
if ready_to_infer:
@@ -438,20 +438,24 @@ def find_spanning_type(type1, type2):
438438
return PyrexTypes.c_double_type
439439
return result_type
440440

441-
def aggressive_spanning_type(types, might_overflow):
441+
def aggressive_spanning_type(types, might_overflow, pos):
442442
result_type = reduce(find_spanning_type, types)
443443
if result_type.is_reference:
444444
result_type = result_type.ref_base_type
445445
if result_type.is_const:
446446
result_type = result_type.const_base_type
447+
if result_type.is_cpp_class:
448+
result_type.check_nullary_constructor(pos)
447449
return result_type
448450

449-
def safe_spanning_type(types, might_overflow):
451+
def safe_spanning_type(types, might_overflow, pos):
450452
result_type = reduce(find_spanning_type, types)
451453
if result_type.is_const:
452454
result_type = result_type.const_base_type
453455
if result_type.is_reference:
454456
result_type = result_type.ref_base_type
457+
if result_type.is_cpp_class:
458+
result_type.check_nullary_constructor(pos)
455459
if result_type.is_pyobject:
456460
# In theory, any specific Python type is always safe to
457461
# infer. However, inferring str can cause some existing code

Cython/Shadow.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,66 @@
11
# cython.* namespace for pure mode.
22
__version__ = "0.18-pre"
33

4+
# Shamelessly copied from Cython/minivect/minitypes.py
5+
6+
class _ArrayType(object):
7+
8+
is_array = True
9+
subtypes = ['dtype']
10+
11+
def __init__(self, dtype, ndim, is_c_contig=False, is_f_contig=False,
12+
inner_contig=False, broadcasting=None):
13+
self.dtype = dtype
14+
self.ndim = ndim
15+
self.is_c_contig = is_c_contig
16+
self.is_f_contig = is_f_contig
17+
self.inner_contig = inner_contig or is_c_contig or is_f_contig
18+
self.broadcasting = broadcasting
19+
20+
def __repr__(self):
21+
axes = [":"] * self.ndim
22+
if self.is_c_contig:
23+
axes[-1] = "::1"
24+
elif self.is_f_contig:
25+
axes[0] = "::1"
26+
27+
return "%s[%s]" % (self.dtype, ", ".join(axes))
28+
29+
def index_type(base_type, item):
30+
"""
31+
Support array type creation by slicing, e.g. double[:, :] specifies
32+
a 2D strided array of doubles. The syntax is the same as for
33+
Cython memoryviews.
34+
"""
35+
assert isinstance(item, (tuple, slice))
36+
37+
def verify_slice(s):
38+
if s.start or s.stop or s.step not in (None, 1):
39+
raise minierror.InvalidTypeSpecification(
40+
"Only a step of 1 may be provided to indicate C or "
41+
"Fortran contiguity")
42+
43+
if isinstance(item, tuple):
44+
step_idx = None
45+
for idx, s in enumerate(item):
46+
verify_slice(s)
47+
if s.step and (step_idx or idx not in (0, len(item) - 1)):
48+
raise minierror.InvalidTypeSpecification(
49+
"Step may only be provided once, and only in the "
50+
"first or last dimension.")
51+
52+
if s.step == 1:
53+
step_idx = idx
54+
55+
return _ArrayType(base_type, len(item),
56+
is_c_contig=step_idx == len(item) - 1,
57+
is_f_contig=step_idx == 0)
58+
else:
59+
verify_slice(item)
60+
return _ArrayType(base_type, 1, is_c_contig=bool(item.step))
61+
62+
# END shameless copy
63+
464
compiled = False
565

666
_Unspecified = object()
@@ -241,6 +301,8 @@ def __call__(self, *arg):
241301
def __repr__(self):
242302
return self.name or str(self._basetype)
243303

304+
__getitem__ = index_type
305+
244306
class _FusedType(CythonType):
245307
pass
246308

Cython/Utility/CppConvert.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
cdef extern from *:
77
cdef cppclass string "std::string":
8+
string()
89
string(char* c_str, size_t size)
910

1011
@cname("{{cname}}")
@@ -147,6 +148,7 @@ cdef object {{cname}}(const_cpp_set[X]& s):
147148

148149
cdef extern from *:
149150
cdef cppclass pair "std::pair" [T, U]:
151+
pair()
150152
pair(T&, U&)
151153

152154
@cname("{{cname}}")

Cython/Utility/CythonFunction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ __pyx_FusedFunction_getitem(__pyx_FusedFunctionObject *self, PyObject *idx)
700700
Py_DECREF(string);
701701
}
702702

703-
sep = PyUnicode_FromString(", ");
703+
sep = PyUnicode_FromString("|");
704704
if (sep)
705705
signature = PyUnicode_Join(sep, list);
706706
__pyx_err:

0 commit comments

Comments
 (0)