binutils-gdb/gdb/python
Tom de Vries 912bc231ab [gdb/python] Add gdbpy_handle_gdb_exception
I've recently committed two patches:
- commit 2f8cd40c37 ("[gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often")
- commit fbf8e4c35c ("[gdb/python] Use GDB_PY_SET_HANDLE_EXCEPTION more often")
which use the macros GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
more often, with the goal of making things more consistent.

Having done that, I wondered if a better approach could be possible.

Consider GDB_PY_HANDLE_EXCEPTION:
...
 /* Use this in a 'catch' block to convert the exception to a Python
    exception and return nullptr.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
   do {						\
     gdbpy_convert_exception (Exception);	\
     return nullptr;				\
   } while (0)
...

The macro nicely codifies how python handles exceptions:
- setting an error condition using some PyErr_Set* variant, and
- returning a value implying that something went wrong
presumably with the goal that using the macro will mean not accidentally:
- forgetting to return on error, or
- returning the wrong value on error.

The problems are that:
- the macro hides control flow, specifically the return statement, and
- the macro hides the return value.

For example, when reading somewhere:
...
  catch (const gdb_exception &except)
    {
      GDB_PY_HANDLE_EXCEPTION (except);
    }
...
in order to understand what this does, you have to know that the macro
returns, and that it returns nullptr.

Add a template gdbpy_handle_gdb_exception:
...
template<typename T>
[[nodiscard]] T
gdbpy_handle_gdb_exception (T val, const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
which can be used instead:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (nullptr, except);
    }
...

[ Initially I tried this:
...
template<auto val>
[[nodiscard]] auto
gdbpy_handle_gdb_exception (const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
with which the usage is slightly better looking:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception<nullptr> (except);
    }
...
but I ran into trouble with older gcc compilers. ]

While still a single statement, we now have it clear:
- that the statement returns,
- what value the statement returns.

[ FWIW, this could also be handled by say:
...
-      GDB_PY_HANDLE_EXCEPTION (except);
+      GDB_PY_HANDLE_EXCEPTION_AND_RETURN_VAL (except, nullptr);
...
but I still didn't find the fact that it returns easy to spot.

Alternatively, this is the simplest form we could use:
...
      return gdbpy_convert_exception (e), nullptr;
...
but the pairing would not necessarily survive a copy/paste/edit cycle. ]

Also note how making the value explicit makes it easier to check for
consistency:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (-1, except);
    }

  if (PyErr_Occurred ())
    return -1;
...
given that we do use the explicit constants almost everywhere else.

Compared to using GDB_PY_HANDLE_EXCEPTION, there is the burden now to specify
the return value, but I assume that this will be generally copy-pasted and
therefore present no problem.

Also, there's no longer a guarantee that there's an immediate return, but I
assume that nodiscard making sure that the return value is not silently
ignored is sufficient mitigation.

For now, re-implement GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
in terms of gdbpy_handle_gdb_exception.

Follow-up patches will eliminate the macros.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
..
lib/gdb gdb dap: introduce stopOnEntry option 2024-09-13 14:19:34 -06:00
py-all-events.def Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-arch.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-auto-load.c gdb: remove gdbcmd.h 2024-04-25 12:59:02 -04:00
py-block.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-bpevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-breakpoint.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-cmd.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-connection.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-continueevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-dap.c Don't allow new-ui to start the TUI 2024-05-17 09:39:41 -06:00
py-disasm.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-event-types.def Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-event.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-event.h Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-events.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-evtregistry.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-evts.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-exitedevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-finishbreakpoint.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-frame.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-framefilter.c gdb: drop struct keyword when using bound_minimal_symbol 2024-08-12 10:31:09 -04:00
py-function.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-gdb-readline.c [gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often 2024-08-27 09:20:18 +02:00
py-inferior.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-infevents.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-infthread.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-instruction.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-instruction.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-lazy-string.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-linetable.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-membuf.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-mi.c [gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often 2024-08-27 09:20:18 +02:00
py-micmd.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-newobjfileevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-objfile.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-param.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-prettyprint.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-progspace.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-record-btrace.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-record-btrace.h python: Add clear() to gdb.Record. 2024-08-14 11:20:56 +02:00
py-record-full.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-record-full.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-record.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-record.h python: Introduce gdb.RecordAuxiliary class. 2024-08-14 11:20:56 +02:00
py-ref.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-registers.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-signalevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-stopevent.c [gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often 2024-08-27 09:20:18 +02:00
py-stopevent.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00
py-symbol.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-symtab.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-threadevent.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-tui.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-type.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-uiout.h gdb: Buffer output streams during events that might download debuginfo 2024-01-19 00:18:00 -05:00
py-unwind.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-utils.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-value.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
py-varobj.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
py-xmethods.c gdb, gdbserver, gdbsupport: remove includes of early headers 2024-03-26 21:13:22 -04:00
python-config.py Run isort 2024-04-02 11:21:39 -06:00
python-internal.h [gdb/python] Add gdbpy_handle_gdb_exception 2024-09-24 13:06:32 +02:00
python.c Automatically add types to Python modules 2024-09-23 13:44:59 -06:00
python.h Update copyright year range in header of all files managed by GDB 2024-01-12 15:49:57 +00:00