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