diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index e1bf72eb93..fb54944317 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -1873,15 +1873,15 @@ write_module_class(ostream &out, Object *obj) { return_flags |= RF_preserve_null; } string expected_params; - write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, - AT_no_args, return_flags, false); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, + AT_no_args, return_flags, false)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } break; @@ -1919,19 +1919,19 @@ write_module_class(ostream &out, Object *obj) { out << " }\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, return_flags, false); - - if (rfi->second._wrapper_type != WT_one_param) { - out << " Py_INCREF(Py_NotImplemented);\n"; - out << " return Py_NotImplemented;\n"; - } else { - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, return_flags, false)) { + if (rfi->second._wrapper_type != WT_one_param) { + out << " Py_INCREF(Py_NotImplemented);\n"; + out << " return Py_NotImplemented;\n"; + } else { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return nullptr;\n"; + } } out << "}\n\n"; } @@ -1970,40 +1970,42 @@ write_module_class(ostream &out, Object *obj) { if (!setattr_remaps.empty()) { out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; string expected_params; - write_function_forset(out, setattr_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, true); - - out << " Py_DECREF(args);\n"; - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 8, expected_params); - out << ");\n"; - out << " }\n"; + if (!write_function_forset(out, setattr_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, RF_int | RF_decref_args, true)) { + out << " Py_DECREF(args);\n"; + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 8, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n\n"; + } } else { out << " PyErr_Format(PyExc_TypeError,\n"; out << " \"can't set attributes of built-in/extension type '%s'\",\n"; out << " Py_TYPE(self)->tp_name);\n"; + out << " return -1;\n\n"; } - out << " return -1;\n\n"; out << " } else { // __delattr__\n"; if (!delattr_remaps.empty()) { string expected_params; - write_function_forset(out, delattr_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, true); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 8, expected_params); - out << ");\n"; - out << " }\n"; + if (!write_function_forset(out, delattr_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, true)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 8, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } } else { out << " PyErr_Format(PyExc_TypeError,\n"; out << " \"can't delete attributes of built-in/extension type '%s'\",\n"; out << " Py_TYPE(self)->tp_name);\n"; + out << " return -1;\n"; } - out << " return -1;\n"; out << " }\n"; out << "}\n\n"; @@ -2036,12 +2038,12 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, - true, true, AT_single_arg, - RF_pyobject | RF_err_null, true); - - // out << " PyErr_Clear();\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, + true, true, AT_single_arg, + RF_pyobject | RF_err_null, true)) { + // out << " PyErr_Clear();\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } break; @@ -2069,15 +2071,15 @@ write_module_class(ostream &out, Object *obj) { out << " }\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } break; @@ -2115,20 +2117,27 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; + bool always_returns = true; out << " if (arg != nullptr) { // __setitem__\n"; - write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index"); + if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, + true, true, AT_single_arg, RF_int, false, true, "index")) { + always_returns = false; + } out << " } else { // __delitem__\n"; - write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index"); + if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, false, true, "index")) { + always_returns = false; + } out << " }\n\n"; - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!always_returns) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } out << "}\n\n"; } break; @@ -2181,22 +2190,29 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; + bool always_returns = true; out << " if (arg2 != nullptr) { // __setitem__\n"; out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, false); + if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, RF_int | RF_decref_args, false)) { + always_returns = false; + } out << " Py_DECREF(args);\n"; out << " } else { // __delitem__\n"; - write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false); + if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, false)) { + always_returns = false; + } out << " }\n\n"; - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!always_returns) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } out << "}\n\n"; } break; @@ -2416,23 +2432,29 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; - + bool always_returns = true; out << " if (arg2 != nullptr && arg2 != Py_None) {\n"; out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_pyobject | RF_err_null | RF_decref_args, true); + if (!write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, RF_pyobject | RF_err_null | RF_decref_args, true)) { + always_returns = false; + } out << " Py_DECREF(args);\n"; out << " } else {\n"; - write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_pyobject | RF_err_null, true); + if (!write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_pyobject | RF_err_null, true)) { + always_returns = false; + } out << " }\n\n"; - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!always_returns) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } break; @@ -2483,15 +2505,15 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_compare, false, true); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, RF_compare, false, true)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } out << "}\n\n"; } break; @@ -2642,10 +2664,10 @@ write_module_class(ostream &out, Object *obj) { out << " {\n"; string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_err_null, false); - - out << " break;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, + AT_single_arg, RF_pyobject | RF_err_null, false)) { + out << " break;\n"; + } out << " }\n"; } @@ -2670,10 +2692,10 @@ write_module_class(ostream &out, Object *obj) { out << " {\n"; string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false); - - out << " break;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, + AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false)) { + out << " break;\n"; + } out << " }\n"; } } @@ -3779,17 +3801,24 @@ write_function_for_name(ostream &out, Object *obj, } } + bool always_returns; if (strip_keyword_args) { // None of the remaps take any keyword arguments, so let's check that // we take none. This saves some checks later on. indent(out, 4) << "if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) {\n"; if (min_args == 1 && min_args == 1) { indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_single_arg, return_flags, + true, !all_nonconst); } else { - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_varargs, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_varargs, return_flags, + true, !all_nonconst); } } else if (min_args == 1 && max_args == 1 && args_type == AT_varargs) { // We already checked that the args tuple has only one argument, so @@ -3797,16 +3826,23 @@ write_function_for_name(ostream &out, Object *obj, indent(out, 4) << "{\n"; indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_single_arg, return_flags, + true, !all_nonconst); } else { indent(out, 4) << "{\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, args_type, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, args_type, + return_flags, true, !all_nonconst); } indent(out, 4) << "}\n"; - indent(out, 4) << "break;\n"; + if (!always_returns) { + indent(out, 4) << "break;\n"; + } } // In NDEBUG case, fall through to the error at end of function. @@ -3917,24 +3953,22 @@ write_function_for_name(ostream &out, Object *obj, } int min_args = min(max_required_args, mii->first); - write_function_forset(out, mii->second, min_args, mii->first, expected_params, 2, - coercion_allowed, true, args_type, return_flags, true, !all_nonconst); + if (!write_function_forset(out, mii->second, min_args, mii->first, + expected_params, 2, coercion_allowed, true, + args_type, return_flags, true, !all_nonconst)) { + if (args_type != AT_no_args) { + out << " if (!_PyErr_OCCURRED()) {\n" + << " "; + if ((return_flags & ~RF_pyobject) == RF_err_null) { + out << "return "; + } + out << "Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n" + << " }\n"; - // This block is often unreachable for many functions... maybe we can - // figure out a way in the future to better determine when it will be and - // won't be necessary to write this out. - if (args_type != AT_no_args) { - out << " if (!_PyErr_OCCURRED()) {\n" - << " "; - if ((return_flags & ~RF_pyobject) == RF_err_null) { - out << "return "; + error_return(out, 2, return_flags); } - out << "Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - << " }\n"; - - error_return(out, 2, return_flags); } } @@ -4137,10 +4171,11 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { } indent(out, 6) << "case " << max_args << ": {\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 8, false, false, - AT_varargs, return_flags, true, false); - - indent(out, 8) << "break;\n"; + if (!write_function_forset(out, mii->second, min_args, max_args, + expected_params, 8, false, false, + AT_varargs, return_flags, true, false)) { + indent(out, 8) << "break;\n"; + } indent(out, 6) << "}\n"; } indent(out, 4) << "}\n"; @@ -4387,7 +4422,7 @@ bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { * first parameter. This is a special-case hack for one of the slot * functions. */ -void InterfaceMakerPythonNative:: +bool InterfaceMakerPythonNative:: write_function_forset(ostream &out, const std::set &remapsin, int min_num_args, int max_num_args, @@ -4398,13 +4433,14 @@ write_function_forset(ostream &out, const string &first_pexpr) { if (remapsin.empty()) { - return; + return false; } FunctionRemap *remap = nullptr; std::set::iterator sii; bool all_nonconst = false; + bool always_returns = true; if (verify_const) { // Check if all of the remaps are non-const. If so, we only have to check @@ -4460,6 +4496,7 @@ write_function_forset(ostream &out, indent(out, indent_level) << "if (Dtool_ExtractArg(&arg, args, kwds, \"" << first_param_name << "\")) {\n"; indent_level += 2; args_type = AT_single_arg; + always_returns = false; } if (remapsin.size() > 1) { @@ -4471,6 +4508,7 @@ write_function_forset(ostream &out, std::vector::const_iterator sii; int num_coercion_possible = 0; + bool caught_all = false; sii = remaps.begin(); while (sii != remaps.end()) { remap = *(sii++); @@ -4485,7 +4523,16 @@ write_function_forset(ostream &out, } } - if (verify_const && (remap->_has_this && !remap->_const_method)) { + if (caught_all) { + indent(out, indent_level) + << " // [DCE] -2 \n"; + remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); + out << "\n"; + continue; + } + + bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); + if (remap_verify_const) { // If it's a non-const method, we only allow a non-const this. indent(out, indent_level) << "if (!DtoolInstance_IS_CONST(self)) {\n"; @@ -4501,17 +4548,23 @@ write_function_forset(ostream &out, // NB. We don't pass on report_errors here because we want it to // silently drop down to the next overload. - write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level + 2, - false, false, args_type, return_flags, - check_exceptions, first_pexpr); + if (write_function_instance(out, remap, min_num_args, max_num_args, + expected_params, indent_level + 2, + false, false, args_type, return_flags, + check_exceptions, first_pexpr)) { + // The rest of the overloads are dead code. + if (!remap_verify_const) { + caught_all = true; + //indent(out, indent_level) << " // caught all cases here\n"; + } + } indent(out, indent_level) << "}\n\n"; } // Go through one more time, but allow coercion this time. - if (coercion_allowed) { - for (sii = remaps.begin(); sii != remaps.end(); sii ++) { + if (coercion_allowed && !caught_all) { + for (sii = remaps.begin(); sii != remaps.end(); ++sii) { remap = (*sii); if (!is_remap_coercion_possible(remap)) { indent(out, indent_level) @@ -4521,7 +4574,16 @@ write_function_forset(ostream &out, continue; } - if (verify_const && (remap->_has_this && !remap->_const_method)) { + if (caught_all) { + indent(out, indent_level) + << " // [DCE] -2 \n"; + remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); + out << "\n"; + continue; + } + + bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); + if (remap_verify_const) { indent(out, indent_level) << "if (!DtoolInstance_IS_CONST(self)) {\n"; } else { @@ -4534,14 +4596,24 @@ write_function_forset(ostream &out, out << "\n"; string ignore_expected_params; - write_function_instance(out, remap, min_num_args, max_num_args, - ignore_expected_params, indent_level + 2, - true, false, args_type, return_flags, - check_exceptions, first_pexpr); + if (write_function_instance(out, remap, min_num_args, max_num_args, + ignore_expected_params, indent_level + 2, + true, false, args_type, return_flags, + check_exceptions, first_pexpr)) { + // The rest of the overloads are dead code. + if (!remap_verify_const) { + caught_all = true; + //indent(out, indent_level) << " // caught all cases here\n"; + } + } indent(out, indent_level) << "}\n\n"; } } + + if (!caught_all) { + always_returns = false; + } } else { // There is only one possible overload with this number of parameters. // Just call it. @@ -4553,11 +4625,13 @@ write_function_forset(ostream &out, remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); out << "\n"; - write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level, - coercion_allowed, report_errors, - args_type, return_flags, - check_exceptions, first_pexpr); + if (!write_function_instance(out, remap, min_num_args, max_num_args, + expected_params, indent_level, + coercion_allowed, report_errors, + args_type, return_flags, + check_exceptions, first_pexpr)) { + always_returns = false; + } } // Close the brace we opened earlier. @@ -4586,10 +4660,14 @@ write_function_forset(ostream &out, out << "#else\n"; error_raise_return(out, indent_level, return_flags, "TypeError", msg.str()); out << "#endif\n"; + } else { + always_returns = false; } indent_level -= 2; indent(out, indent_level) << "}\n"; } + + return always_returns; } /** @@ -4616,8 +4694,11 @@ write_function_forset(ostream &out, * If first_pexpr is not empty, it represents the preconverted value of the * first parameter. This is a special-case hack for one of the slot * functions. + * + * Returns true if the function returns unconditionally, false if it may fall + * through and additional error handling code is needed. */ -void InterfaceMakerPythonNative:: +bool InterfaceMakerPythonNative:: write_function_instance(ostream &out, FunctionRemap *remap, int min_num_args, int max_num_args, string &expected_params, int indent_level, @@ -4673,7 +4754,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, --max_num_args; } } - nassertv(num_params <= (int)remap->_parameters.size()); + nassertr(num_params <= (int)remap->_parameters.size(), false); } bool only_pyobjects = true; @@ -4784,7 +4865,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, // We should only ever have to consider optional arguments for functions // taking a variable number of arguments. - nassertv(args_type == AT_varargs || args_type == AT_keyword_args); + nassertr(args_type == AT_varargs || args_type == AT_keyword_args, false); } string reported_name = remap->_parameters[pn]._name; @@ -6372,12 +6453,18 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "}\n"; } - // Close the extra braces opened earlier. - while (open_scopes > 0) { - indent_level -= 2; - indent(out, indent_level) << "}\n"; + // If we were in a scope + bool always_returns = true; + if (open_scopes > 0) { + always_returns = false; - --open_scopes; + // Close the extra braces opened earlier. + while (open_scopes > 0) { + indent_level -= 2; + indent(out, indent_level) << "}\n"; + + --open_scopes; + } } if (clear_error && !report_errors) { @@ -6389,7 +6476,10 @@ write_function_instance(ostream &out, FunctionRemap *remap, if (min_version > 0) { // Close the #if PY_VERSION_HEX check. out << "#endif\n"; + always_returns = false; } + + return always_returns; } /** @@ -6758,15 +6848,16 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - "}\n\n"; + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + } + out << "}\n\n"; // Write out a setitem if this is not a read-only property. if (!property->_setter_remaps.empty()) { @@ -6823,16 +6914,15 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_single_arg, - RF_int, false, false, "index"); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, + true, AT_single_arg, RF_int, false, false, "index")) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } out << "}\n\n"; } @@ -6852,16 +6942,16 @@ write_getset(ostream &out, Object *obj, Property *property) { property->_inserter->_remaps.end()); string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_single_arg, - RF_pyobject | RF_err_null, false, false, "index"); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, + true, AT_single_arg, RF_pyobject | RF_err_null, + false, false, "index")) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } } @@ -6921,16 +7011,16 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_pyobject | RF_err_null, false, true); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - " return nullptr;\n" - "}\n\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, RF_pyobject | RF_err_null, false, true)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n" + " }\n" + " return nullptr;\n"; + } + out << "}\n\n"; // Write out a setitem if this is not a read-only property. if (!property->_setter_remaps.empty()) { @@ -6970,10 +7060,11 @@ write_getset(ostream &out, Object *obj, Property *property) { property->_deleter->_remaps.end()); string expected_params; - write_function_forset(out, remaps, 1, 1, - expected_params, 4, true, true, AT_single_arg, - RF_int, false, false); - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 1, 1, + expected_params, 4, true, true, AT_single_arg, + RF_int, false, false)) { + out << " return -1;\n"; + } } else { out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n" " return -1;\n"; @@ -6999,17 +7090,17 @@ write_getset(ostream &out, Object *obj, Property *property) { << " Py_INCREF(value);\n"; string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_varargs, - RF_int | RF_decref_args, false, false); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " Py_DECREF(args);\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 2, 2, + expected_params, 2, true, true, AT_varargs, + RF_int | RF_decref_args, false, false)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " Py_DECREF(args);\n"; + out << " return -1;\n"; + } out << "}\n\n"; } @@ -7050,15 +7141,15 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - "}\n\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n" + " }\n"; + } + out << "}\n\n"; } } @@ -7246,16 +7337,15 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, - expected_params, 2, true, true, AT_single_arg, - RF_int, false, false); - - out << " if (!_PyErr_OCCURRED()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, + true, AT_single_arg, RF_int, false, false)) { + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + } out << "}\n\n"; } } diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index b387cf0001..dfac95247e 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -151,7 +151,7 @@ private: int collapse_default_remaps(std::map > &map_sets, int max_required_args); - void write_function_forset(std::ostream &out, + bool write_function_forset(std::ostream &out, const std::set &remaps, int min_num_args, int max_num_args, std::string &expected_params, int indent_level, @@ -161,7 +161,7 @@ private: bool verify_const = true, const std::string &first_expr = std::string()); - void write_function_instance(std::ostream &out, FunctionRemap *remap, + bool write_function_instance(std::ostream &out, FunctionRemap *remap, int min_num_args, int max_num_args, std::string &expected_params, int indent_level, bool coercion_allowed, bool report_errors,