Commit 18e8b745 authored by Robert Bradshaw's avatar Robert Bradshaw

Support enums in C++ classes.

This fixes #1473.
parent 439c7b83
......@@ -1457,6 +1457,9 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1
for attr in self.attributes:
declare = getattr(attr, 'declare', None)
if declare:
attr.declare(scope)
attr.analyse_declarations(scope)
for func in func_attributes(self.attributes):
defined_funcs.append(func)
......
......@@ -3625,8 +3625,10 @@ 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':
elif s.systring == 'ctypedef':
return p_ctypedef_statement(s, ctx)
elif s.sy == 'IDENT' and s.systring in struct_enum_union:
return p_struct_enum(s, s.position(), ctx)
else:
node = p_c_func_or_var_declaration(s, s.position(), ctx)
if decorators is not None:
......
......@@ -3627,11 +3627,12 @@ class CEnumType(CType):
signed = 1
rank = -1 # Ranks below any integer type
def __init__(self, name, cname, typedef_flag):
def __init__(self, name, cname, typedef_flag, namespace=None):
self.name = name
self.cname = cname
self.values = []
self.typedef_flag = typedef_flag
self.namespace = namespace
self.default_value = "(%s) 0" % self.empty_declaration_code()
def __str__(self):
......@@ -3646,13 +3647,24 @@ class CEnumType(CType):
if pyrex or for_display:
base_code = self.name
else:
if self.typedef_flag:
if self.namespace:
base_code = "%s::%s" % (
self.namespace.empty_declaration_code(), self.cname)
elif self.typedef_flag:
base_code = self.cname
else:
base_code = "enum %s" % self.cname
base_code = public_decl(base_code, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def specialize(self, values):
if self.namespace:
namespace = self.namespace.specialize(values)
if namespace != self.namespace:
return CEnumType(
self.name, self.cname, self.typedef_flag, namespace)
return self
def create_to_py_utility_code(self, env):
self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
env.use_utility_code(TempitaUtilityCode.load_cached(
......
......@@ -546,6 +546,8 @@ class Scope(object):
if scope:
entry.type.scope = scope
self.type_entries.append(entry)
if self.is_cpp_class_scope:
entry.type.namespace = self.outer_scope.lookup(self.name).type
return entry
def declare_cpp_class(self, name, scope,
......@@ -613,11 +615,16 @@ class Scope(object):
visibility = 'private', api = 0, create_wrapper = 0):
if name:
if not cname:
if self.in_cinclude or (visibility == 'public' or api):
if (self.in_cinclude or visibility == 'public'
or visibility == 'extern' or api):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
type = PyrexTypes.CEnumType(name, cname, typedef_flag)
if self.is_cpp_class_scope:
namespace = self.outer_scope.lookup(self.name).type
else:
namespace = None
type = PyrexTypes.CEnumType(name, cname, typedef_flag, namespace)
else:
type = PyrexTypes.c_anon_enum_type
entry = self.declare_type(name, type, pos, cname = cname,
......
......@@ -11,6 +11,10 @@ cdef extern from "cpp_nested_classes_support.h":
@staticmethod
my_int negate(my_int)
cdef cppclass TypedClass[T]:
enum MyEnum:
value
def test_nested_classes():
"""
>>> test_nested_classes()
......@@ -28,3 +32,8 @@ def test_nested_classes():
def test_nested_typedef(py_x):
cdef A.my_int x = py_x
assert A.negate(x) == -py_x
def test_nested_enum(TypedClass[double].MyEnum x):
return x == 3
def test_
\ No newline at end of file
......@@ -16,3 +16,16 @@ public:
return -x;
}
};
template <typename T>
class TypedClass {
public:
enum MyEnum {
value = 39
};
union MyUnion {
T typed_value;
int int_value;
}
typedef T MyType;
};
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