Commit 17e2f2c5 authored by Robert Bradshaw's avatar Robert Bradshaw

Add support for typedefs in C++ classes.

parent 8b642621
......@@ -3625,6 +3625,8 @@ def p_cpp_class_attribute(s, ctx):
decorators = p_decorators(s)
if s.systring == 'cppclass':
return p_cpp_class_definition(s, s.position(), ctx)
if s.systring == 'ctypedef':
return p_ctypedef_statement(s, ctx)
else:
node = p_c_func_or_var_declaration(s, s.position(), ctx)
if decorators is not None:
......
......@@ -316,7 +316,7 @@ def public_decl(base_code, dll_linkage):
else:
return base_code
def create_typedef_type(name, base_type, cname, is_external=0):
def create_typedef_type(name, base_type, cname, is_external=0, namespace=None):
is_fused = base_type.is_fused
if base_type.is_complex or is_fused:
if is_external:
......@@ -329,7 +329,7 @@ def create_typedef_type(name, base_type, cname, is_external=0):
return base_type
else:
return CTypedefType(name, base_type, cname, is_external)
return CTypedefType(name, base_type, cname, is_external, namespace)
class CTypedefType(BaseType):
......@@ -353,12 +353,13 @@ class CTypedefType(BaseType):
subtypes = ['typedef_base_type']
def __init__(self, name, base_type, cname, is_external=0):
def __init__(self, name, base_type, cname, is_external=0, namespace=None):
assert not base_type.is_complex
self.typedef_name = name
self.typedef_cname = cname
self.typedef_base_type = base_type
self.typedef_is_external = is_external
self.typedef_namespace = namespace
def invalid_value(self):
return self.typedef_base_type.invalid_value()
......@@ -372,6 +373,8 @@ class CTypedefType(BaseType):
base_code = self.typedef_name
else:
base_code = public_decl(self.typedef_cname, dll_linkage)
if self.typedef_namespace is not None and not pyrex:
base_code = "%s::%s" % (self.typedef_namespace.empty_declaration_code(), base_code)
return self.base_declaration_code(base_code, entity_code)
def as_argument_type(self):
......@@ -482,8 +485,8 @@ class CTypedefType(BaseType):
def error_condition(self, result_code):
if self.typedef_is_external:
if self.exception_value:
condition = "(%s == (%s)%s)" % (
result_code, self.typedef_cname, self.exception_value)
condition = "(%s == %s)" % (
result_code, self.cast_code(self.exception_value))
if self.exception_check:
condition += " && PyErr_Occurred()"
return condition
......
......@@ -495,13 +495,18 @@ class Scope(object):
def declare_typedef(self, name, base_type, pos, cname = None,
visibility = 'private', api = 0):
if not cname:
if self.in_cinclude or (visibility == 'public' or api):
if self.in_cinclude or (visibility != 'private' or api):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
try:
if self.is_cpp_class_scope:
namespace = self.outer_scope.lookup(self.name).type
else:
namespace = None
type = PyrexTypes.create_typedef_type(name, base_type, cname,
(visibility == 'extern'))
(visibility == 'extern'),
namespace)
except ValueError as e:
error(pos, e.args[0])
type = PyrexTypes.error_type
......
......@@ -7,17 +7,24 @@ cdef extern from "cpp_nested_classes_support.h":
cppclass C:
int cube(int)
B* createB()
ctypedef int my_int
@staticmethod
my_int negate(my_int)
def test():
def test_nested_classes():
"""
>>> test()
>>> test_nested_classes()
"""
cdef A a
cdef A.B b
assert b.square(3) == 9
cdef A.B.C c
assert c.cube(3) == 27
cdef A.B *b_ptr = a.createB()
assert b_ptr.square(4) == 16
del b_ptr
def test_nested_typedef(py_x):
cdef A.my_int x = py_x
assert A.negate(x) == -py_x
......@@ -11,4 +11,8 @@ public:
B* createB() {
return new B();
}
typedef int my_int;
static my_int negate(my_int x) {
return -x;
}
};
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