Skip to content

Commit 9d162d5

Browse files
authored
[cpyrt] Cache anonymous-enum constant values in CPPDataMember (#94)
dm_get computed the value of an anonymous-enum constant but did not cache it. kIsEnumPrep is cleared on the first access and kIsEnumType was never set, so later accesses skipped the enum branch and read the instance memory at the member's offset instead. Cache the value in fDescription and set kIsEnumType, as the named-enum path does.
1 parent 83b0fca commit 9d162d5

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

‎src/cpyrt/CPPDataMember.cxx‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,17 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj,
8888
}
8989

9090
if (interop::IsEnumConstant(dm->fScope)) {
91-
// anonymous enum
92-
return pyval_from_enum(interop::ResolveEnum(dm->fScope), nullptr, nullptr,
93-
dm->fScope);
91+
// anonymous enum; cache the value in fDescription like the named case
92+
// above: once kIsEnumPrep is cleared this block is not reached again
93+
PyObject* pyval = pyval_from_enum(interop::ResolveEnum(dm->fScope),
94+
nullptr, nullptr, dm->fScope);
95+
if (pyval) {
96+
Py_DECREF(dm->fDescription);
97+
dm->fDescription = pyval;
98+
dm->fFlags |= kIsEnumType;
99+
Py_INCREF(pyval);
100+
return pyval;
101+
}
94102
}
95103
}
96104
// non-initialized or public data accesses through class (e.g. by help())

‎test/test_datatypes.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,3 +2736,21 @@ def test55_qt_cache_alias_collision(self):
27362736
ns.take_schar("e")
27372737
ns.take_int8(101)
27382738
raises(TypeError, ns.take_int8, "e")
2739+
2740+
2741+
class TestANONENUM:
2742+
def test01_anonymous_enum_repeated_access(self):
2743+
"""An anonymous-enum constant keeps its value across accesses"""
2744+
2745+
import cppjit
2746+
2747+
cppjit.cppdef("""\
2748+
namespace AnonEnum { struct Holder { enum { kAnon = 42 }; }; }""")
2749+
2750+
h = cppjit.gbl.AnonEnum.Holder()
2751+
2752+
# the value is computed on the first access and cached; without the
2753+
# cache later accesses fall through to the data-member converter
2754+
assert h.kAnon == 42
2755+
assert h.kAnon == 42
2756+
assert h.kAnon == 42

0 commit comments

Comments
 (0)