Commit 30546e71 authored by Stefan Behnel's avatar Stefan Behnel

Only declare the C++ no-args constructor as "nogil" if the base classes allow it.

Closes #2157.
parent edde08f7
......@@ -1729,12 +1729,7 @@ class NewExprNode(AtomicExprNode):
self.type = error_type
return
self.cpp_check(env)
constructor = type.scope.lookup(u'<init>')
if constructor is None:
func_type = PyrexTypes.CFuncType(
type, [], exception_check='+', nogil=True)
type.scope.declare_cfunction(u'<init>', func_type, self.pos)
constructor = type.scope.lookup(u'<init>')
constructor = type.get_constructor(self.pos)
self.class_type = type
self.entry = constructor
self.type = constructor.type
......
......@@ -3817,6 +3817,23 @@ class CppClassType(CType):
func_type = func_type.base_type
return func_type.return_type
def get_constructor(self, pos):
constructor = self.scope.lookup('<init>')
if constructor is not None:
return constructor
# Otherwise: automatically declare no-args default constructor.
# Make it "nogil" if the base classes allow it.
nogil = True
for base in self.base_classes:
base_constructor = base.scope.lookup('<init>')
if base_constructor and not base_constructor.type.nogil:
nogil = False
break
func_type = CFuncType(self, [], exception_check='+', nogil=nogil)
return self.scope.declare_cfunction(u'<init>', func_type, pos)
def check_nullary_constructor(self, pos, msg="stack allocated"):
constructor = self.scope.lookup(u'<init>')
if constructor is not None and best_match([], constructor.all_alternatives()) is None:
......
......@@ -9,7 +9,7 @@ cdef extern from "shapes.h" namespace "shapes":
float area()
cdef cppclass Ellipse(Shape):
Ellipse(int a, int b) except +
Ellipse(int a, int b) nogil except +
cdef cppclass Circle(Ellipse):
int radius
......@@ -32,6 +32,7 @@ cdef extern from "shapes.h" namespace "shapes":
int constructor_count, destructor_count
def test_new_del():
"""
>>> test_new_del()
......@@ -45,6 +46,7 @@ def test_new_del():
del rect, circ
print constructor_count-c, destructor_count-d
def test_default_constructor():
"""
>>> test_default_constructor()
......@@ -56,6 +58,20 @@ def test_default_constructor():
finally:
del shape
def test_constructor_nogil():
"""
>>> test_constructor_nogil()
True
"""
with nogil:
shape = new Ellipse(4, 5)
try:
return 62 < shape.area() < 63 or shape.area()
finally:
del shape
def test_rect_area(w, h):
"""
>>> test_rect_area(3, 4)
......@@ -67,6 +83,7 @@ def test_rect_area(w, h):
finally:
del rect
def test_overload_bint_int():
"""
>>> test_overload_bint_int()
......@@ -83,6 +100,7 @@ def test_overload_bint_int():
del rect1
del rect2
def test_square_area(w):
"""
>>> test_square_area(15)
......@@ -95,6 +113,7 @@ def test_square_area(w):
finally:
del sqr
cdef double get_area(Rectangle s):
return s.area()
......@@ -110,6 +129,7 @@ def test_value_call(int w):
finally:
del sqr
def get_destructor_count():
return destructor_count
......@@ -126,6 +146,7 @@ def test_stack_allocation(int w, int h):
print rect.method(<int>5)
return destructor_count
cdef class EmptyHolder:
cdef Empty empty
......@@ -148,6 +169,7 @@ def test_class_member():
assert destructor_count - start_destructor_count == 2, \
destructor_count - start_destructor_count
def test_derived_class_member():
"""
>>> test_derived_class_member()
......@@ -161,6 +183,7 @@ def test_derived_class_member():
assert destructor_count - start_destructor_count == 2, \
destructor_count - start_destructor_count
cdef class TemplateClassMember:
cdef vector[int] x
cdef vector[vector[Empty]] vec
......@@ -190,6 +213,9 @@ cdef int f(int x):
return x
def test_nested_del():
"""
>>> test_nested_del()
"""
cdef vector[vector_int_ptr] v
v.push_back(new vector[int]())
del v[0]
......
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