From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id FxgTI2tChmpFXTEAWB0awg (envelope-from ) for ; Wed, 19 Aug 2026 19:55:23 -0400 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (768-bit key; unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=gxci7tYj; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 79F6D1E0A3; Wed, 19 Aug 2026 19:55:23 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 4EF0F1E09B for ; Wed, 19 Aug 2026 19:55:22 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3F9F04B99F5B for ; Wed, 19 Aug 2026 23:55:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3F9F04B99F5B Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (768-bit key, unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=gxci7tYj Received: from omta038.useast.a.cloudfilter.net (omta038.useast.a.cloudfilter.net [44.202.169.37]) by sourceware.org (Postfix) with ESMTPS id 086C34B9DB53 for ; Wed, 19 Aug 2026 23:54:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 086C34B9DB53 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 086C34B9DB53 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=44.202.169.37 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787183684; cv=none; b=kFDItJUQY6ZXQWVFWyTk7txKAe9UHw5+d++w6G6Vhe6CxNZioK0Oa1wJoIVClg17Va0SJ0anLUDW+IUUeG4f9tw4HGb+IlNHEq3Ezpd2jTQeng9YxHCT13+n0FnZ5LWbzq3dimZD1nuppZ7UVI1Shymy/9umdfaKrmJQX25a+sU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787183684; c=relaxed/simple; bh=NelZGP2KmcGSCvY18QX5JlNFfAkUDrHBDcfw3qu6K78=; h=DKIM-Signature:From:Date:Subject:MIME-Version:Message-Id:To; b=YnSWwsDy3C8s9NgMCblAaScriDLTHupXlplZ26i4/5AT0atpY8Z9pxBlCNh0XAm6oVO8m+KgZ4VOypF2pcBYE0GIPqcEZJgT7Gqh6uXsDaDDNZ0S57toR3f5PBWLaXc2srHanfvuGqoCj+9kxtcUOmDmhKhUMxbeqapoeOTjKkw= ARC-Authentication-Results: i=1; sourceware.org; dkim=policy (768-bit key, unprotected) header.d=tromey.com header.i=@tromey.com header.a=rsa-sha256 header.s=default header.b=gxci7tYj reason="signing key too small" DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 086C34B9DB53 Received: from eig-obgw-6005b.ext.cloudfilter.net ([10.0.30.162]) by cmsmtp with ESMTPS id wpGNwcrgQJFmFwq7HwIVV9; Wed, 19 Aug 2026 23:54:43 +0000 Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTPS id wq7GwJoR0OYlBwq7HwYxFS; Wed, 19 Aug 2026 23:54:43 +0000 X-Authority-Analysis: v=2.4 cv=FLYbx/os c=1 sm=1 tr=0 ts=6a864243 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=IkcTkHD0fZMA:10 a=Sv0fKeRqtYgA:10 a=ItBw4LHWJt0A:10 a=uKwXjxvOVeMkr_FtqnwA:9 a=QEXdDO2ut3YA:10 a=DCx65vhANUyCzuf5D8fC:22 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=MFlCL4KUU3H8OHqnUL6/hWQtTPa+v75WuYW53BIVyQA=; b=gxci7tYjDT7VWX+SaJlpSl2j0Y LEJmrubz0OoBRrE9q6c2hdeoIaS7lFq24NaX0LhoJnFd2KFRFePy4Em5twm27JcW+WjIFznPwQSd2 W+kXvozfYRDPrjFVX8FLoCjQ4; Received: from 75-166-225-82.hlrn.qwest.net ([75.166.225.82]:36824 helo=[192.168.122.1]) by box5379.bluehost.com with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.99.5) (envelope-from ) id 1wwq7G-000000020o1-28j4; Wed, 19 Aug 2026 17:54:42 -0600 From: Tom Tromey Date: Wed, 19 Aug 2026 17:54:42 -0600 Subject: [PATCH 4/4] Convert frapy_richcompare to safety API MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260819-python-safety-frame-v1-4-563cb6b9e7a6@tromey.com> References: <20260819-python-safety-frame-v1-0-563cb6b9e7a6@tromey.com> In-Reply-To: <20260819-python-safety-frame-v1-0-563cb6b9e7a6@tromey.com> To: gdb-patches@sourceware.org Cc: Tom Tromey X-Mailer: b4 0.14.3 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 75.166.225.82 X-Source-L: No X-Exim-ID: 1wwq7G-000000020o1-28j4 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 75-166-225-82.hlrn.qwest.net ([192.168.122.1]) [75.166.225.82]:36824 X-Source-Auth: tom+tromey.com X-Email-Count: 5 X-Org: HG=bhshared;ORG=bluehost; X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-CMAE-Envelope: MS4xfC3ZPJACYMK7UX6tzXFwCYbL4XPy7JGAA5EDPAZTZoRXLHvji4p8Mq3MMCAL6hoNbhIObJ6gjKtKxm/IkTs80xN82XN/plHPaG2a0EkbuRcbwLh/Izp9 6fKInjr1lIF8kuF0ql7o4ldX29TLlvHMq4v1n/8CPwDfBIWNmZ1d4dvKBFYcfBwOV9JZ+l7iu/Xck37o6M4jJJ23i2LJwzDUlzs= X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org This converts frapy_richcompare to the Python safety API. A new wrap_richcompare template function is added. As 'richcompare' can return three results (or throw), the wrapped method returns a std::optional; this is documented by the wrapper. I considered a specialization of wrap_richcompare that automatically ensures that the compared-to value is of the same class as 'this' -- this would be useful in a few (but not all) spots in gdb. However this seemed like a refinement that could easily be added later. This also removes a part of a comment that I think is incorrect. --- gdb/python/py-frame.c | 24 +++++++++++------------- gdb/python/py-safety.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 4dd174cf5ae..4aedd7db563 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -141,6 +141,9 @@ struct frame_object : public PyObject /* The static link for this frame. */ gdbpy_ref<> static_link (); + /* Implementation of the Python richcompare API. */ + std::optional richcompare (gdbpy_borrowed_ref<> other, int op); + static PyTypeObject *corresponding_object_type; }; @@ -482,30 +485,25 @@ gdbpy_frame_stop_reason_string (gdbpy_borrowed_ref<> args, return unwind_stop_reason_to_string ((enum unwind_stop_reason) reason); } -/* Implements the equality comparison for Frame objects. - All other comparison operators will throw a TypeError Python exception, - as they aren't valid for frames. */ +/* Implements the equality comparison for Frame objects. */ -static PyObject * -frapy_richcompare (PyObject *self, PyObject *other, int op) +std::optional +frame_object::richcompare (gdbpy_borrowed_ref<> other, int op) { int result; if (!PyObject_TypeCheck (other, &frame_object_type) || (op != Py_EQ && op != Py_NE)) - return py_notimplemented ().release (); + return std::nullopt; - frame_object *self_frame = (frame_object *) self; - frame_object *other_frame = (frame_object *) other; + frame_object *other_frame = other; - if (self_frame->frame_id == other_frame->frame_id) + if (frame_id == other_frame->frame_id) result = Py_EQ; else result = Py_NE; - if (op == result) - return py_true ().release (); - return py_false ().release (); + return op == result; } PyTypeObject *frame_object::corresponding_object_type = &frame_object_type; @@ -623,7 +621,7 @@ PyTypeObject frame_object_type = { "GDB frame object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - frapy_richcompare, /* tp_richcompare */ + wrap_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h index 06324868817..e2cd8bc3f30 100644 --- a/gdb/python/py-safety.h +++ b/gdb/python/py-safety.h @@ -364,4 +364,36 @@ wrap_setter (PyObject *arg, PyObject *value, void *closure) return 0; } +/* A function that wraps a richcompare method. + + A Python tp_richcompare function can either raise an exception, + return True or False, or return "not implemented". The wrapped + method must return a std::optional, which allows all these + results: exceptions are simply thrown, true and false are ordinary + returns, and the return of an empty optional means "not + implemented". */ +template (C::*M) (gdbpy_borrowed_ref<>, int)> +PyObject * +wrap_richcompare (PyObject *arg, PyObject *value, int op) +{ + using namespace safety_details; + try + { + C *self = static_cast (arg); + std::optional result = (self->*M) (value, op); + if (result.has_value ()) + return to_python (*result); + return py_notimplemented ().release (); + } + catch (const gdb_python_exception &pye) + { + gdb_assert (PyErr_Occurred () != nullptr); + return nullptr; + } + catch (const gdb_exception &exc) + { + return gdbpy_handle_gdb_exception (nullptr, exc); + } +} + #endif /* GDB_PYTHON_PY_SAFETY_H */ -- 2.49.0