diff --git a/src/cpyrt/CPPDataMember.cxx b/src/cpyrt/CPPDataMember.cxx index c2543dc..b7a5787 100644 --- a/src/cpyrt/CPPDataMember.cxx +++ b/src/cpyrt/CPPDataMember.cxx @@ -88,9 +88,17 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj, } if (interop::IsEnumConstant(dm->fScope)) { - // anonymous enum - return pyval_from_enum(interop::ResolveEnum(dm->fScope), nullptr, nullptr, - dm->fScope); + // anonymous enum; cache the value in fDescription like the named case + // above: once kIsEnumPrep is cleared this block is not reached again + PyObject* pyval = pyval_from_enum(interop::ResolveEnum(dm->fScope), + nullptr, nullptr, dm->fScope); + if (pyval) { + Py_DECREF(dm->fDescription); + dm->fDescription = pyval; + dm->fFlags |= kIsEnumType; + Py_INCREF(pyval); + return pyval; + } } } // non-initialized or public data accesses through class (e.g. by help()) diff --git a/test/test_datatypes.py b/test/test_datatypes.py index e5f5f56..b172c2e 100644 --- a/test/test_datatypes.py +++ b/test/test_datatypes.py @@ -2736,3 +2736,21 @@ def test55_qt_cache_alias_collision(self): ns.take_schar("e") ns.take_int8(101) raises(TypeError, ns.take_int8, "e") + + +class TestANONENUM: + def test01_anonymous_enum_repeated_access(self): + """An anonymous-enum constant keeps its value across accesses""" + + import cppjit + + cppjit.cppdef("""\ + namespace AnonEnum { struct Holder { enum { kAnon = 42 }; }; }""") + + h = cppjit.gbl.AnonEnum.Holder() + + # the value is computed on the first access and cached; without the + # cache later accesses fall through to the data-member converter + assert h.kAnon == 42 + assert h.kAnon == 42 + assert h.kAnon == 42