Skip to content

Commit 5655e97

Browse files
committed
interrogate: fix misbehaving == and != operator if only < is defined
Fixes comparison of two empty RenderEffects objects
1 parent 7f11dc1 commit 5655e97

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

dtool/src/interrogate/interfaceMakerPythonNative.cxx

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,6 +2570,8 @@ write_module_class(ostream &out, Object *obj) {
25702570
out << " return nullptr;\n";
25712571
out << " }\n\n";
25722572

2573+
bool have_eq = false;
2574+
bool have_ne = false;
25732575
for (Function *func : obj->_methods) {
25742576
std::set<FunctionRemap*> remaps;
25752577
if (!func) {
@@ -2590,8 +2592,10 @@ write_module_class(ostream &out, Object *obj) {
25902592
op_type = "Py_LE";
25912593
} else if (fname == "operator ==") {
25922594
op_type = "Py_EQ";
2595+
have_eq = true;
25932596
} else if (fname == "operator !=") {
25942597
op_type = "Py_NE";
2598+
have_ne = true;
25952599
} else if (fname == "operator >") {
25962600
op_type = "Py_GT";
25972601
} else if (fname == "operator >=") {
@@ -2616,6 +2620,43 @@ write_module_class(ostream &out, Object *obj) {
26162620
}
26172621

26182622
if (has_local_richcompare) {
2623+
if (have_eq && !have_ne) {
2624+
// Generate a not-equal function from the equal function.
2625+
for (Function *func : obj->_methods) {
2626+
std::set<FunctionRemap*> remaps;
2627+
if (!func) {
2628+
continue;
2629+
}
2630+
const string &fname = func->_ifunc.get_name();
2631+
if (fname != "operator ==") {
2632+
continue;
2633+
}
2634+
for (FunctionRemap *remap : func->_remaps) {
2635+
if (is_remap_legal(remap) && remap->_has_this && (remap->_args_type == AT_single_arg)) {
2636+
remaps.insert(remap);
2637+
}
2638+
}
2639+
out << " case Py_NE: // from Py_EQ\n";
2640+
out << " {\n";
2641+
2642+
string expected_params;
2643+
write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false,
2644+
AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false);
2645+
2646+
out << " break;\n";
2647+
out << " }\n";
2648+
}
2649+
}
2650+
else if (!have_eq && !slots.count("tp_compare")) {
2651+
// Generate an equals function.
2652+
out << " case Py_EQ:\n";
2653+
out << " return PyBool_FromLong(DtoolInstance_Check(arg) && DtoolInstance_VOID_PTR(self) == DtoolInstance_VOID_PTR(arg));\n";
2654+
if (!have_ne) {
2655+
out << " case Py_NE:\n";
2656+
out << " return PyBool_FromLong(!DtoolInstance_Check(arg) || DtoolInstance_VOID_PTR(self) != DtoolInstance_VOID_PTR(arg));\n";
2657+
}
2658+
}
2659+
26192660
// End of switch block
26202661
out << " }\n\n";
26212662
out << " if (_PyErr_OCCURRED()) {\n";
@@ -6048,8 +6089,13 @@ write_function_instance(ostream &out, FunctionRemap *remap,
60486089
return_flags &= ~RF_pyobject;
60496090

60506091
} else if (return_null && TypeManager::is_bool(remap->_return_type->get_new_type())) {
6051-
indent(out, indent_level)
6052-
<< "return Dtool_Return_Bool(" << return_expr << ");\n";
6092+
if (return_flags & RF_invert_bool) {
6093+
indent(out, indent_level)
6094+
<< "return Dtool_Return_Bool(!(" << return_expr << "));\n";
6095+
} else {
6096+
indent(out, indent_level)
6097+
<< "return Dtool_Return_Bool(" << return_expr << ");\n";
6098+
}
60536099
return_flags &= ~RF_pyobject;
60546100

60556101
} else if (return_null && TypeManager::is_pointer_to_PyObject(remap->_return_type->get_new_type())) {
@@ -6415,7 +6461,12 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
64156461
indent(out, indent_level)
64166462
<< "return PyString_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n";
64176463
out << "#endif\n";
6418-
} else {
6464+
}
6465+
else if (return_flags & RF_invert_bool) {
6466+
indent(out, indent_level)
6467+
<< "return Dtool_WrapValue(!(" << return_expr << "));\n";
6468+
}
6469+
else {
64196470
indent(out, indent_level)
64206471
<< "return Dtool_WrapValue(" << return_expr << ");\n";
64216472
}

dtool/src/interrogate/interfaceMakerPythonNative.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ class InterfaceMakerPythonNative : public InterfaceMakerPython {
115115

116116
// This raises a KeyError on falsey (or -1) return value.
117117
RF_raise_keyerror = 0x4000,
118+
119+
// Invert boolean return value.
120+
RF_invert_bool = 0x8000,
118121
};
119122

120123
class SlottedFunctionDef {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy