Commit 1a6fcd39 authored by Robert Bradshaw's avatar Robert Bradshaw

C++ class member test.

parent 1e92f37a
......@@ -990,6 +990,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
have_entries, (py_attrs, py_buffers, memoryview_slices) = \
scope.get_refcounted_entries(include_weakref=True)
cpp_class_attrs = [entry for entry in scope.var_entries if entry.type.is_cpp_class]
new_func_entry = scope.lookup_here("__new__")
if base_type or (new_func_entry and new_func_entry.is_special
......@@ -998,7 +999,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else:
unused_marker = 'CYTHON_UNUSED '
need_self_cast = type.vtabslot_cname or have_entries
need_self_cast = type.vtabslot_cname or have_entries or cpp_class_attrs
code.putln("")
code.putln(
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {"
......@@ -1036,9 +1037,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.vtabslot_cname,
struct_type_cast, type.vtabptr_cname))
for entry in scope.var_entries:
if entry.type.is_cpp_class:
code.putln("new(&(p->%s)) %s();" % (entry.cname, entry.type.cname));
for entry in cpp_class_attrs:
code.putln("new((void*)&(p->%s)) %s();" %
(entry.cname, entry.type.cname));
for entry in py_attrs:
if scope.is_internal or entry.name == "__weakref__":
......@@ -1086,8 +1087,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
weakref_slot = scope.lookup_here("__weakref__")
_, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries()
cpp_class_attrs = [entry for entry in scope.var_entries if entry.type.is_cpp_class]
if py_attrs or memoryview_slices or weakref_slot in scope.var_entries:
if (py_attrs
or cpp_class_attrs
or memoryview_slices
or weakref_slot in scope.var_entries):
self.generate_self_cast(scope, code)
# call the user's __dealloc__
......@@ -1095,9 +1100,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if weakref_slot in scope.var_entries:
code.putln("if (p->__weakref__) PyObject_ClearWeakRefs(o);")
for entry in scope.var_entries:
if entry.type.is_cpp_class:
code.putln("p->%s.~%s();" % (entry.cname, entry.type.cname));
for entry in cpp_class_attrs:
class_name = entry.type.cname.split("::")[-1]
code.putln("p->%s.~%s();" % (entry.cname, class_name));
for entry in py_attrs:
code.put_xdecref("p->%s" % entry.cname, entry.type, nanny=False)
......
......@@ -1774,6 +1774,7 @@ class CClassScope(ClassScope):
if constructor is not None and \
PyrexTypes.best_match([], constructor.all_alternatives()) is None:
error(pos, "C++ class must have a no-arg constructor to be a member of an extension type; use a pointer instead")
self.use_utility_code(Code.UtilityCode("#include <new>"))
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
self.var_entries.append(entry)
......
......@@ -33,6 +33,9 @@ cdef extern from "shapes.h" namespace "shapes":
int side
Square(int)
cdef cppclass Empty(Shape):
pass
int constructor_count, destructor_count
def test_new_del():
......@@ -81,3 +84,22 @@ def test_value_call(int w):
return get_area(sqr[0]), get_area(rect[0])
finally:
del sqr
cdef class EmptyHolder:
cdef Empty empty
def test_class_member():
"""
>>> test_class_member()
"""
start_constructor_count = constructor_count
start_destructor_count = destructor_count
e1 = EmptyHolder()
assert constructor_count - start_constructor_count == 1, \
constructor_count - start_constructor_count
e2 = EmptyHolder()
assert constructor_count - start_constructor_count == 2, \
constructor_count - start_constructor_count
del e1, e2
assert destructor_count - start_destructor_count == 2, \
destructor_count - start_destructor_count
......@@ -48,6 +48,10 @@ namespace shapes {
int radius;
};
class Empty : public Shape {
float area() { return 0; }
};
}
#endif
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