From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kGqhJ0dkl2daIRwAWB0awg (envelope-from ) for ; Mon, 27 Jan 2025 05:47:35 -0500 Received: by simark.ca (Postfix, from userid 112) id 9F1A51E105; Mon, 27 Jan 2025 05:47:35 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.3 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.0 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (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 C1AF11E08E for ; Mon, 27 Jan 2025 05:47:34 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6DFBE3858430 for ; Mon, 27 Jan 2025 10:47:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6DFBE3858430 Received: from us-smtp-delivery-114.mimecast.com (us-smtp-delivery-114.mimecast.com [170.10.133.114]) by sourceware.org (Postfix) with ESMTP id 832D7385843B for ; Mon, 27 Jan 2025 10:45:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 832D7385843B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=labware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=labware.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 832D7385843B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.114 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1737974755; cv=none; b=pOOAk7HnKXgq2NKn9cNdZKbQyG6qJfECNA/ZXRkEd/zrgqYj4O+uMXHGA7Am6bsl04kwGLvTKqNqlxii2HNIqdqbVYkbxaK0AhdoaSHoZ5IvKFu8oLOxz6ENgK/MlhvpZaRGHxNeGeL0kYwJTOWwoYX6F6et4aS5gmRhf94unRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1737974755; c=relaxed/simple; bh=TbOiVUxFLZsE7JyEav6SSS9dMmKeQ5esXqeyfAcoGa0=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=oJiCr9Rl9GWmkMdbXkfI78dDWNHEpHn3UT6AqBYXfSyGcdzFhxGtSEUSL05FMY/uGhVeuUnxbcwFdQZFPORdGlYaJQoLBRN/coop15/O4DwM7vhXFs+hnLG5F104t1AxqEtUd1n+Ha7e/Rct03SoQeJA+da7FGVTjMmbpC8h0yI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 832D7385843B Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10lp2041.outbound.protection.outlook.com [104.47.70.41]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-616-GQK2G70NNF2wg4CmRMS8rA-1; Mon, 27 Jan 2025 05:45:54 -0500 X-MC-Unique: GQK2G70NNF2wg4CmRMS8rA-1 X-Mimecast-MFC-AGG-ID: GQK2G70NNF2wg4CmRMS8rA Received: from SA0PR17MB4314.namprd17.prod.outlook.com (2603:10b6:806:e7::16) by DM4PR17MB6954.namprd17.prod.outlook.com (2603:10b6:8:18e::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8377.22; Mon, 27 Jan 2025 10:45:51 +0000 Received: from SA0PR17MB4314.namprd17.prod.outlook.com ([fe80::38a7:a6f2:3b95:bc26]) by SA0PR17MB4314.namprd17.prod.outlook.com ([fe80::38a7:a6f2:3b95:bc26%5]) with mapi id 15.20.8377.021; Mon, 27 Jan 2025 10:45:51 +0000 From: Jan Vrany To: gdb-patches@sourceware.org CC: Jan Vrany Subject: [RFC 4/9] gdb/python: preserve identity for gdb.Type objects Date: Mon, 27 Jan 2025 10:44:30 +0000 Message-ID: <20250127104435.823519-5-jan.vrany@labware.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250127104435.823519-1-jan.vrany@labware.com> References: <20250127104435.823519-1-jan.vrany@labware.com> X-ClientProxiedBy: LO4P123CA0584.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:276::15) To SA0PR17MB4314.namprd17.prod.outlook.com (2603:10b6:806:e7::16) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SA0PR17MB4314:EE_|DM4PR17MB6954:EE_ X-MS-Office365-Filtering-Correlation-Id: b0cf342a-aee7-45a8-e290-08dd3ebfc494 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|366016|1800799024 X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?O/lR1oEVwuwwgcJhXMunEOJ9Ile/JeGvgB1dQrOjh0JaZ0Qz6r7BvWcziJxG?= =?us-ascii?Q?NbG1QgngtbDbe4hpWaNbpcR7jnOtqOf6LPCDUjY9jVRE/qtM8MnV7IUEp3Dr?= =?us-ascii?Q?KldfaTAeuqxDZGjGLzQU1lWVH/QQRbtivVe/gXXOaRyyxflvkaCkF9XprxtD?= =?us-ascii?Q?nKF3pP4wbv691jZqj5R/oLgC73i9dkv168+iF8pApri3JieHrxewVXQhkden?= =?us-ascii?Q?5mfYxXHqsQjY95VTHk5lTLzc9N4vFk+OLIQfaeNUjPpm74I4DkHWTUhEWIEu?= =?us-ascii?Q?NqzG4aXGrvB1hvl9+uv9oNRm16IFvMGqGDZH5uwRmXeEKCf3tOU/xVeOE3td?= =?us-ascii?Q?VVTbtc/4aRZtVN3exlElqjUX1HdjwpM2i7E1uKTeuUoxQ0ca1Kgkre60GYzU?= =?us-ascii?Q?1bPOgnk19g8omr4me81oE931pTjRh0tK0+XXpghTUSz6gRXpohE41V8ND7cV?= =?us-ascii?Q?+BGqGWy8h8vRlksDbFWQe+T99BDzmZ7LFnIV/O0bPfO72eqmsU0sBwTSRbA3?= =?us-ascii?Q?DxnyZA3tFYGDQs8+cbJxNTWnlEVNvd0Q+3NASixOY8WdRAWv+xPWgqklYwMH?= =?us-ascii?Q?5nsRKSaNp23WZvgQhDISgNLMufW7Uc/AKGPBlQBWfuNP1IL/6ln9Xbs9j0VH?= =?us-ascii?Q?LIHVgi5kQfI4Gl/yOiJSg3TRmWPvfI/cKJspRhupBTLqyL9tFjZb9kSnfEws?= =?us-ascii?Q?VWwgZgQdLUbnXRHEr4bKqi4nUquob1/kHr7YOdqIhW2a7weNIxyaPn0Z+mQr?= =?us-ascii?Q?wmKRAhimjtRPNQKKFYVs1lDrQwYQAp6fh7lZttias2MujYla8R3dQldoqWdh?= =?us-ascii?Q?FYPZ9SVcm5UsOYZTladegQCbUQ97tv5H6/sVTXvHPf20NZMM7zAdOoU5vXYq?= =?us-ascii?Q?TbFsVSZV+YNmQ/nOgXV5WN7yQ9kfOqZiO8qsW7JEJ/9lxX1GKEX0+7M0zpEn?= =?us-ascii?Q?IVWWB64sBP1QRcjYafgEdNqkKBBaQkKKREKfai8CiJLnEqUInlNDRrOirJay?= =?us-ascii?Q?qcEK0vau99UzueusZu0mBnG/VzCyp/JhCiDnOhaQ+PK/hcS1JjLXYQJQtRWP?= =?us-ascii?Q?3+GsKfQEoLqnEp455KB6QKUba7Vj7Nz0qpgbal25es7ZjAPOXBupDJeVfgRC?= =?us-ascii?Q?6PfmsgGbfutvnu9iwerpAqVakJFY+rpPR+aRj37xTU8TbBtlqUBT7jCcqT1O?= =?us-ascii?Q?mDu6QDSUheylymzLWa88Iz/ljGLALp4pOEzWNHVrlux2AAHPDOlD5ikyddQ9?= =?us-ascii?Q?Hk3wXR1G5uc1drIpeVw8vIYyhsi6ok6FbmGNpVCAivUkgXPEnAfL4tSSKuuQ?= =?us-ascii?Q?vSlRdcS+MUlOq1NJtJujrxdTp6Ws9BwojBDGS7sDnmJ3xIER7ec9g0yDIEgx?= =?us-ascii?Q?le2udUvtnWghWfgp46/1vZbzMLd2?= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SA0PR17MB4314.namprd17.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(376014)(366016)(1800799024); DIR:OUT; SFP:1102 X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?KGo85P8hWO2J999s7UluHFyG6ofGM9qx3DTB8Lz/J++OKUSasvqP4PDidUd5?= =?us-ascii?Q?E1RPojx41PgiAvtKHHggBsdcWO1pie7/xlvM9qk2268pko/sZxU4Hcf/2yiE?= =?us-ascii?Q?tZ88vykLmtxGeSQ2kOxI5Wn5kKioFbWNpXFDhQGWqpIXF35DQhK9vV5V5Xvo?= =?us-ascii?Q?92y0JzCf/h4RcIbIZIjCc03b/4oQI+YKrMvGQL6rR6sx6i1isV9PFqnvIVR3?= =?us-ascii?Q?nPmy7pBDVpg2SWNnhj4HFoGbPnpmdjkocv5mSlSRuMWejV+eUGGZZCcyiH6C?= =?us-ascii?Q?PlY1FllX2ofydhr9u81WiUxGCI2sNSVX1OmJsLyiuk0JIXEKGU6o7KfQ1TRj?= =?us-ascii?Q?+6V2N5wddOo42ekKnLbX1pijBZq68TMQ9Tyoy7q0x6nkTNvpFYGrhx9Ot4vL?= =?us-ascii?Q?QcZe1Ul4qwWFQ4/74vw8dQ7XC1f2RoAiBrpMQiakSCsvGHjaH1oiXBktNSpK?= =?us-ascii?Q?AQM7Jy0mEA7/97X8rP/VcMd6jAxqN3NBZO/nLNPBjtItKjHFyrat8cGtt6AK?= =?us-ascii?Q?qyMXDG7MN2xTm8mipksdYvsR7AfgTSe1sRcmkVBlPJSGnlVlzwqYc7nOFqc4?= =?us-ascii?Q?AWcHOM1h/h7JcDVxt+8xsrHwH/7FA8cEujVp7/ghcXTy8AegNFlGqlUiktii?= =?us-ascii?Q?qBQZZD3vn0EIl3NOdJu89FnxTkjwitPQtQ2s6pm0T9KjklCJ1O+Uz/16u/Yw?= =?us-ascii?Q?oUgM5ZUC9rK6VB9hXqWnEk60J3jLTm10K7WIHi/vWEqueYMqN2X1nTQuASQC?= =?us-ascii?Q?PeKqtwGdwqgmeMkZhDspa0BXcpIM32dTk83NEsup9GQGGSZKbTjm9F8bNOLH?= =?us-ascii?Q?V1/orQcLcUuPEqKXmtQZ7tq3vV0048AhlIJYrc2gQ5NARGnQjQcsc/GhkjBu?= =?us-ascii?Q?PSTuhgr3CkQ65kXcWjCdQEimg/rSvYbX3al7ORO8gkiFfzPjgniEhtrd4JYO?= =?us-ascii?Q?tePDUaHkE5WQaratDTLmitZa5ENn5yCogd5g3XMi811u63K/oWdWCHshSpY7?= =?us-ascii?Q?WRtrJ4oiWbM8PZFZZQFq91MlUnyCxyC1QoDwWSp+sdhO8O8ssRY72LE7m7xC?= =?us-ascii?Q?8xXHNBZshRYmaNfS661l5nzqUhCKPVNXUVPKNqCOcSZ4NHu7Ib3OkQiV3YHS?= =?us-ascii?Q?Qpd4qOdGBjbWoh+sNK+FnYR19fsJUShGR5DBhWDUBZ4WdkRBkMcF6wyYq3r2?= =?us-ascii?Q?NQ1mGsl5DDwrGlFHcRDyj4nhsUOnT+pBjAb/l4rUB3LrN5cAeme1GUQJwNwz?= =?us-ascii?Q?ldpRnUNKUgFCjbnfnBVX+M3pxIQup5o74faGcj0jIkJyUUkfoWWq/FcYy3RQ?= =?us-ascii?Q?JNM7sV4tshgdiS2/IZn8f69/dnfEHyg713aTKumisbsFMc8RVdYgstp8Y4Z5?= =?us-ascii?Q?eIR/5b9zhD8aOdgruiOQQPCDVm6EQSrdvFqVdSoCXYPcLCIOuqQSrPkXJv0I?= =?us-ascii?Q?v9JBjB5+MW3PBAXjKrk+USMCG5s6wlbc+3G6bpQ2cLNjoHwc3flXgVJ6EChU?= =?us-ascii?Q?kNlnddFuKQ2zPUP//wBT5Ujbs+jMMNUAKkiHzRKSLM4VJeaJzwh2DJk22RpJ?= =?us-ascii?Q?ZyydaDVqeO91s61Tpmc8a454WTcfFRE5qIzzYjH7?= X-OriginatorOrg: labware.com X-MS-Exchange-CrossTenant-Network-Message-Id: b0cf342a-aee7-45a8-e290-08dd3ebfc494 X-MS-Exchange-CrossTenant-AuthSource: SA0PR17MB4314.namprd17.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jan 2025 10:45:51.6020 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b5db0322-1aa0-4c0a-859c-ad0f96966f4c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: lB/KHHAXU60SXOnkF+8FlIiIGNw+6MrlDtWfe2y+rf82oyO9DjM5aw9wQhhDLtU4+07B5X1vS+4w80tGHMkiWw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR17MB6954 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: SsFfvjeek-P94k1jBmlkN5pLJnN_Q_3xc0s9BXIRREg_1737974753 X-Mimecast-Originator: labware.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=WINDOWS-1252 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 commit changes type_to_type_object() so that each it is called with a particular struct type * it returns the very same gdb.Type object. This is done in the same way as for gdb.Symtab objects in earlier commit ("gdb/python: preserve identity for gdb.Symtab objects") except that types may be either objfile-owned or arch-owned. Prior this commit, arch-owned objects we not put into any list (like objfile-owned ones) so they could not be easily looked up. This commit changes the code so arch-owned list are put into per-architecture list which is then used (solely) for looking up arch-owned gdb.Type. Another complication comes from the fact that when objfile is about to be freed, associated gdb.Type instances are not merely invalidated (like it is done with gdb.Symtab or gdb.Symbol objects) but instead the type is copied and the copy is arch-owned. So we need two different "deleters", one for objfile-owned types that copies the type (as before) and then insert the object to per-architecture list and another one for arch-owned types. --- gdb/python/py-type.c | 104 ++++++++++++++++++++++----- gdb/testsuite/gdb.python/py-arch.exp | 5 ++ gdb/testsuite/gdb.python/py-type.exp | 15 ++++ 3 files changed, 105 insertions(+), 19 deletions(-) diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 11a96d52c2e..c9fa6a37250 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -1162,8 +1162,12 @@ typy_richcompare (PyObject *self, PyObject *other, i= nt op) =20 =0C =20 +/* Forward declaration, see below. */ +static void +set_type (type_object *obj, struct type *type); + /* Deleter that saves types when an objfile is being destroyed. */ -struct typy_deleter +struct typy_deleter_for_objfile_owned { void operator() (type_object *obj) { @@ -1181,35 +1185,74 @@ struct typy_deleter =09type_object *next =3D obj->next; =20 =09copied_types.clear (); -=09obj->type =3D copy_type_recursive (obj->type, copied_types); =20 -=09obj->next =3D NULL; -=09obj->prev =3D NULL; +=09/* Set a copied (now arch-owned) type. As a side-effect this +=09 adds OBJ to per-arch list. We do not need to remove it from +=09 per-objfile list since the objfile is going to go completely +=09 anyway. */ +=09set_type (obj, copy_type_recursive (obj->type, copied_types)); =20 =09obj =3D next; } } }; =20 -static const registry::key +/* Deleter that is used when an arch is is about to be freed. */ +struct typy_deleter_for_arch_owned +{ + void operator() (type_object *obj) + { + while (obj) + { +=09type_object *next =3D obj->next; + +=09obj->type =3D nullptr; + +=09obj->next =3D nullptr; +=09obj->prev =3D nullptr; + +=09obj =3D next; + } + } +}; + + + +static const registry::key typy_objfile_data_key; +static const registry::key + typy_gdbarch_data_key; =20 static void set_type (type_object *obj, struct type *type) { obj->type =3D type; - obj->prev =3D NULL; - if (type !=3D nullptr && type->objfile_owner () !=3D nullptr) + obj->prev =3D nullptr; + + /* Can it really happen that type is NULL? */ + if (type !=3D nullptr) { - struct objfile *objfile =3D type->objfile_owner (); + if (type->objfile_owner () !=3D nullptr) +=09{ +=09 struct objfile *objfile =3D type->objfile_owner (); + +=09 obj->next =3D typy_objfile_data_key.get (objfile); +=09 if (obj->next) +=09 obj->next->prev =3D obj; +=09 typy_objfile_data_key.set (objfile, obj); +=09} + else +=09{ +=09 struct gdbarch *arch =3D type->arch_owner (); =20 - obj->next =3D typy_objfile_data_key.get (objfile); - if (obj->next) -=09obj->next->prev =3D obj; - typy_objfile_data_key.set (objfile, obj); +=09 obj->next =3D typy_gdbarch_data_key.get (arch); +=09 if (obj->next) +=09 obj->next->prev =3D obj; +=09 typy_gdbarch_data_key.set (arch, obj); +=09} } else - obj->next =3D NULL; + obj->next =3D nullptr; } =20 static void @@ -1219,13 +1262,19 @@ typy_dealloc (PyObject *obj) =20 if (type->prev) type->prev->next =3D type->next; - else if (type->type !=3D nullptr && type->type->objfile_owner () !=3D nu= llptr) + else if (type->type !=3D nullptr) { - /* Must reset head of list. */ - struct objfile *objfile =3D type->type->objfile_owner (); - - if (objfile) -=09typy_objfile_data_key.set (objfile, type->next); + if (type->type->is_objfile_owned ()) +=09{ +=09 /* Must reset head of list. */ +=09 struct objfile *objfile =3D type->type->objfile_owner (); +=09 typy_objfile_data_key.set (objfile, type->next); +=09} + else +=09{ +=09 struct gdbarch *arch =3D type->type->arch_owner (); +=09 typy_gdbarch_data_key.set (arch, type->next); +=09} } if (type->next) type->next->prev =3D type->prev; @@ -1473,6 +1522,23 @@ type_to_type_object (struct type *type) return gdbpy_handle_gdb_exception (nullptr, except); } =20 + /* Look if there's already a gdb.Type object for given TYPE + and if so, return it. */ + if (type->is_objfile_owned ()) + type_obj =3D typy_objfile_data_key.get (type->objfile_owner ()); + else + type_obj =3D typy_gdbarch_data_key.get (type->arch_owner ()); + + while (type_obj !=3D nullptr) + { + if (type_obj->type =3D=3D type) +=09{ +=09 Py_INCREF (type_obj); +=09 return (PyObject*)type_obj; +=09} + type_obj =3D type_obj->next; + } + type_obj =3D PyObject_New (type_object, &type_object_type); if (type_obj) set_type (type_obj, type); diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.pytho= n/py-arch.exp index 14802ec80a3..aefb9e90eac 100644 --- a/gdb/testsuite/gdb.python/py-arch.exp +++ b/gdb/testsuite/gdb.python/py-arch.exp @@ -104,6 +104,11 @@ foreach_with_prefix test_data { {None None} \ =09"check 'signed' argument can handle non-bool type $bad_type" } =20 +# Test type identity +gdb_test "python print(arch.integer_type(32) is arch.integer_type(32))" \ + "True" \ + "arch.integer_type(32) always return the same Python object" + # Test for gdb.architecture_names(). First we're going to grab the # complete list of architecture names using the 'complete' command. set arch_names [] diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.pytho= n/py-type.exp index 7e469c93c35..c9d4353e488 100644 --- a/gdb/testsuite/gdb.python/py-type.exp +++ b/gdb/testsuite/gdb.python/py-type.exp @@ -324,6 +324,19 @@ proc test_type_equality {} { } } =20 +# Test type identity +proc test_type_identity {} { + gdb_test_no_output "python v1 =3D gdb.parse_and_eval('global_unsigned_= int')" + gdb_test_no_output "python v2 =3D gdb.parse_and_eval('global_unsigned_= int')" + + gdb_test "python print(v1.type is v2.type)" "True" + + gdb_test_no_output "python t1 =3D gdb.lookup_type ('char')" + gdb_test_no_output "python t2 =3D gdb.lookup_type ('char')" + + gdb_test "python print(t1 is t2)" "True" +} + # Test the gdb.Type.is_scalar property. proc test_is_scalar { lang } { if {$lang =3D=3D "c++"} { @@ -376,6 +389,7 @@ if { [build_inferior "${binfile}" "c"] =3D=3D 0 } { test_is_scalar "c" test_is_signed "c" test_type_equality + test_type_identity } } =20 @@ -392,6 +406,7 @@ if { [build_inferior "${binfile}-cxx" "c++"] =3D=3D 0 }= { test_is_scalar "c++" test_is_signed "c++" test_type_equality + test_type_identity } } =20 --=20 2.45.2