)]}'
{
  "commit": "912bc231ab157fb05e988d8752ea348c3e65111f",
  "tree": "46dfafdaa4cdfd90475b05e56cf8f11f9bd18109",
  "parents": [
    "6848938272157eb6532c189d6fcebec9d2dc33e8"
  ],
  "author": {
    "name": "Tom de Vries",
    "email": "tdevries@suse.de",
    "time": "Tue Sep 24 13:06:32 2024 +0200"
  },
  "committer": {
    "name": "Tom de Vries",
    "email": "tdevries@suse.de",
    "time": "Tue Sep 24 13:06:32 2024 +0200"
  },
  "message": "[gdb/python] Add gdbpy_handle_gdb_exception\n\nI\u0027ve recently committed two patches:\n- commit 2f8cd40c37a (\"[gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often\")\n- commit fbf8e4c35c2 (\"[gdb/python] Use GDB_PY_SET_HANDLE_EXCEPTION more often\")\nwhich use the macros GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION\nmore often, with the goal of making things more consistent.\n\nHaving done that, I wondered if a better approach could be possible.\n\nConsider GDB_PY_HANDLE_EXCEPTION:\n...\n /* Use this in a \u0027catch\u0027 block to convert the exception to a Python\n    exception and return nullptr.  */\n #define GDB_PY_HANDLE_EXCEPTION(Exception)\t\\\n   do {\t\t\t\t\t\t\\\n     gdbpy_convert_exception (Exception);\t\\\n     return nullptr;\t\t\t\t\\\n   } while (0)\n...\n\nThe macro nicely codifies how python handles exceptions:\n- setting an error condition using some PyErr_Set* variant, and\n- returning a value implying that something went wrong\npresumably with the goal that using the macro will mean not accidentally:\n- forgetting to return on error, or\n- returning the wrong value on error.\n\nThe problems are that:\n- the macro hides control flow, specifically the return statement, and\n- the macro hides the return value.\n\nFor example, when reading somewhere:\n...\n  catch (const gdb_exception \u0026except)\n    {\n      GDB_PY_HANDLE_EXCEPTION (except);\n    }\n...\nin order to understand what this does, you have to know that the macro\nreturns, and that it returns nullptr.\n\nAdd a template gdbpy_handle_gdb_exception:\n...\ntemplate\u003ctypename T\u003e\n[[nodiscard]] T\ngdbpy_handle_gdb_exception (T val, const gdb_exception \u0026e)\n{\n  gdbpy_convert_exception (e);\n  return val;\n}\n...\nwhich can be used instead:\n...\n  catch (const gdb_exception \u0026except)\n    {\n      return gdbpy_handle_gdb_exception (nullptr, except);\n    }\n...\n\n[ Initially I tried this:\n...\ntemplate\u003cauto val\u003e\n[[nodiscard]] auto\ngdbpy_handle_gdb_exception (const gdb_exception \u0026e)\n{\n  gdbpy_convert_exception (e);\n  return val;\n}\n...\nwith which the usage is slightly better looking:\n...\n  catch (const gdb_exception \u0026except)\n    {\n      return gdbpy_handle_gdb_exception\u003cnullptr\u003e (except);\n    }\n...\nbut I ran into trouble with older gcc compilers. ]\n\nWhile still a single statement, we now have it clear:\n- that the statement returns,\n- what value the statement returns.\n\n[ FWIW, this could also be handled by say:\n...\n-      GDB_PY_HANDLE_EXCEPTION (except);\n+      GDB_PY_HANDLE_EXCEPTION_AND_RETURN_VAL (except, nullptr);\n...\nbut I still didn\u0027t find the fact that it returns easy to spot.\n\nAlternatively, this is the simplest form we could use:\n...\n      return gdbpy_convert_exception (e), nullptr;\n...\nbut the pairing would not necessarily survive a copy/paste/edit cycle. ]\n\nAlso note how making the value explicit makes it easier to check for\nconsistency:\n...\n  catch (const gdb_exception \u0026except)\n    {\n      return gdbpy_handle_gdb_exception (-1, except);\n    }\n\n  if (PyErr_Occurred ())\n    return -1;\n...\ngiven that we do use the explicit constants almost everywhere else.\n\nCompared to using GDB_PY_HANDLE_EXCEPTION, there is the burden now to specify\nthe return value, but I assume that this will be generally copy-pasted and\ntherefore present no problem.\n\nAlso, there\u0027s no longer a guarantee that there\u0027s an immediate return, but I\nassume that nodiscard making sure that the return value is not silently\nignored is sufficient mitigation.\n\nFor now, re-implement GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION\nin terms of gdbpy_handle_gdb_exception.\n\nFollow-up patches will eliminate the macros.\n\nNo functional changes.\n\nTested on x86_64-linux.\n\nApproved-By: Tom Tromey \u003ctom@tromey.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "82680cdac0a84317831250ffef25b6e9e741f013",
      "old_mode": 33188,
      "old_path": "gdb/python/python-internal.h",
      "new_id": "759e305d40d067865d5613b78d1cc7f7c2698533",
      "new_mode": 33188,
      "new_path": "gdb/python/python-internal.h"
    }
  ]
}
