I just wrote this code that uses a goto statement.
if (PyMethod_Check(attrib_value)) {
PyObject *im_self = PyObject_GetAttrString(attrib_value, "im_self");
if (im_self == Py_None) {
js_value = FunctionTemplate::New(isolate, py_class_method_callback, js_name, signature);
} else {
goto method_counts_as_function;
}
Py_DECREF(im_self);
} else if (PyFunction_Check(attrib_value)) {
method_counts_as_function:
js_value = ((py_function *) py_function_to_template(attrib_value))->js_template->Get(isolate);
templ->Set(js_name, js_value);
} else {
js_value = js_from_py(attrib_value, no_ctx);
templ->Set(js_name, js_value);
}
The intention is to treat certain methods like functions. Normally I would use a &&
in the if statement, something like this:
if (PyMethod_Check(attrib_value) &&
PyObject_GetAttrString(attrib_value, "im_self) != Py_None)
Unfortunately, PyObject_GetAttrString
returns an object with an incremented reference count. I can't decrement the reference count on a value that may or may not have existed in the second part of the short-circuit and.
I feel pretty bad about this since goto statements are considered harmful, but I can't think of a good way to rewrite this without gotos. Is this OK?