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