mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
Add tests for #421: switch with type_conversion lifetime bug
Add both a compiled C++ test (with registered type_conversion) and a pure ChaiScript test (with dynamic objects and custom == operator) to verify that switch case comparisons properly manage object lifetimes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
78d2de0ccf
commit
a329be16ad
@ -1304,3 +1304,97 @@ TEST_CASE("Test if non copyable/movable types can be registered") {
|
||||
chai.add(chaiscript::user_type<Nothing>(), "Nothing");
|
||||
chai.add(chaiscript::constructor<Nothing()>(), "Nothing");
|
||||
}
|
||||
|
||||
// Issue #421: Class with type_conversion from int and "==" operator
|
||||
// causes switch statement to compare destroyed objects.
|
||||
// The switch case comparison must use Function_Push_Pop to properly
|
||||
// manage the lifetime of temporaries created by type conversions.
|
||||
TEST_CASE("Issue #421 - Switch with type_conversion does not compare destroyed objects") {
|
||||
struct MyType {
|
||||
int value;
|
||||
explicit MyType(int v) : value(v) {}
|
||||
};
|
||||
|
||||
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
|
||||
chai.add(chaiscript::user_type<MyType>(), "MyType");
|
||||
chai.add(chaiscript::constructor<MyType(int)>(), "MyType");
|
||||
chai.add(chaiscript::fun(&MyType::value), "value");
|
||||
chai.add(chaiscript::fun([](const MyType &a, const MyType &b) { return a.value == b.value; }), "==");
|
||||
chai.add(chaiscript::type_conversion<int, MyType>([](const int &i) { return MyType(i); }));
|
||||
|
||||
// Test switch with type conversion - the case integer literals must be
|
||||
// converted to MyType via the registered conversion before comparison.
|
||||
// Without Function_Push_Pop, the converted temporaries may be destroyed
|
||||
// before the == operator can compare them.
|
||||
CHECK(chai.eval<int>(R"({
|
||||
var result = 0
|
||||
var obj = MyType(2)
|
||||
switch(obj) {
|
||||
case (1) {
|
||||
result = 1
|
||||
break
|
||||
}
|
||||
case (2) {
|
||||
result = 2
|
||||
break
|
||||
}
|
||||
case (3) {
|
||||
result = 3
|
||||
break
|
||||
}
|
||||
}
|
||||
result
|
||||
})") == 2);
|
||||
|
||||
// Test fall-through with type conversion
|
||||
CHECK(chai.eval<int>(R"({
|
||||
var total = 0
|
||||
var obj = MyType(2)
|
||||
switch(obj) {
|
||||
case (1) {
|
||||
total += 1
|
||||
}
|
||||
case (2) {
|
||||
total += 2
|
||||
}
|
||||
case (3) {
|
||||
total += 4
|
||||
}
|
||||
}
|
||||
total
|
||||
})") == 6);
|
||||
|
||||
// Test matching the first case
|
||||
CHECK(chai.eval<int>(R"({
|
||||
var result = 0
|
||||
var obj = MyType(1)
|
||||
switch(obj) {
|
||||
case (1) {
|
||||
result = 10
|
||||
break
|
||||
}
|
||||
case (2) {
|
||||
result = 20
|
||||
break
|
||||
}
|
||||
}
|
||||
result
|
||||
})") == 10);
|
||||
|
||||
// Test no match
|
||||
CHECK(chai.eval<int>(R"({
|
||||
var result = 0
|
||||
var obj = MyType(5)
|
||||
switch(obj) {
|
||||
case (1) {
|
||||
result = 1
|
||||
break
|
||||
}
|
||||
case (2) {
|
||||
result = 2
|
||||
break
|
||||
}
|
||||
}
|
||||
result
|
||||
})") == 0);
|
||||
}
|
||||
|
||||
50
unittests/switch_type_conversion.chai
Normal file
50
unittests/switch_type_conversion.chai
Normal file
@ -0,0 +1,50 @@
|
||||
// Test for issue #421: switch statement with custom == operator on
|
||||
// dynamic objects must properly manage object lifetimes during
|
||||
// case comparisons.
|
||||
|
||||
class MyType {
|
||||
var value
|
||||
def MyType(v) { this.value = v }
|
||||
}
|
||||
|
||||
def `==`(a, b) : a.is_type("MyType") && b.is_type("MyType") {
|
||||
return a.value == b.value
|
||||
}
|
||||
|
||||
var result = 0
|
||||
var obj = MyType(2)
|
||||
|
||||
switch(obj) {
|
||||
case (MyType(1)) {
|
||||
result = 1
|
||||
break
|
||||
}
|
||||
case (MyType(2)) {
|
||||
result = 2
|
||||
break
|
||||
}
|
||||
case (MyType(3)) {
|
||||
result = 3
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal(result, 2)
|
||||
|
||||
// Also test fall-through with custom == operator
|
||||
var total = 0
|
||||
var obj2 = MyType(2)
|
||||
|
||||
switch(obj2) {
|
||||
case (MyType(1)) {
|
||||
total += 1
|
||||
}
|
||||
case (MyType(2)) {
|
||||
total += 2
|
||||
}
|
||||
case (MyType(3)) {
|
||||
total += 4
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal(total, 6)
|
||||
Loading…
x
Reference in New Issue
Block a user