From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16640 invoked by alias); 9 Nov 2011 18:10:51 -0000 Received: (qmail 16628 invoked by uid 22791); 9 Nov 2011 18:10:49 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,TW_IV X-Spam-Check-By: sourceware.org Received: from qmta15.westchester.pa.mail.comcast.net (HELO qmta15.westchester.pa.mail.comcast.net) (76.96.59.228) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Nov 2011 18:10:34 +0000 Received: from omta20.westchester.pa.mail.comcast.net ([76.96.62.71]) by qmta15.westchester.pa.mail.comcast.net with comcast id v5oH1h0041YDfWL5F6AaAp; Wed, 09 Nov 2011 18:10:34 +0000 Received: from [10.127.248.57] ([65.206.2.68]) by omta20.westchester.pa.mail.comcast.net with comcast id v6AL1h00u1U2a2h3g6ANg4; Wed, 09 Nov 2011 18:10:32 +0000 Subject: Re: [RFA] Python: raise exception on field-related gdb.Type methods if it's not struct or union Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Paul Koning In-Reply-To: Date: Wed, 09 Nov 2011 18:10:00 -0000 Cc: Eli Zaretskii , tromey@redhat.com, gdb-patches@sourceware.org Content-Transfer-Encoding: quoted-printable Message-Id: <087A1A82-39F0-4C58-94BA-07E179DEF564@comcast.net> References: <3A3AF5AE-70E8-43D0-B8CE-DCADFEEF879A@comcast.net> <560557F2-1B8B-4633-8CD6-E63705EEAF0E@comcast.net> <83wrckrcg1.fsf@gnu.org> <37B202A1-DCD5-423E-8E30-55A6F2BE21EF@comcast.net> To: Doug Evans Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-11/txt/msg00241.txt.bz2 This got a bit more complicated once I looked at the testcases. First, it's not just struct and union types that have fields; enum types al= so do. So the common code that checks for valid types has to allow those t= hree. Second, the fields method is also defined for array types, where it returns= a list with a single entry that's a range type. I made that a special cas= e since everything else doesn't apply to array types. Attached is an updated patch including new test cases. paul ChangeLog: 2011-11-09 Paul Koning * python/py-type.c (typy_get_composite): New function. (typy_nonzero): New function. (typy_values): Rename from typy_fields. (typy_fields): New function. (typy_length): Raise exception if not struct, union, or enum type. (typy_getitem): Ditto. (typy_has_key): Ditto. (typy_make_iter): Ditto. testsuite/ChangeLog: 2011-11-09 Paul Koning * gdb.python/py-type.exp: New testcases for exceptions on scalar types. Index: gdb/python/py-type.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/python/py-type.c,v retrieving revision 1.28 diff -u -r1.28 py-type.c --- gdb/python/py-type.c 4 Nov 2011 11:57:04 -0000 1.28 +++ gdb/python/py-type.c 9 Nov 2011 17:36:12 -0000 @@ -308,11 +308,41 @@ /* Return a sequence of all fields. Each field is a gdb.Field object. */ =20 static PyObject * -typy_fields (PyObject *self, PyObject *args) +typy_values (PyObject *self, PyObject *args) { return typy_fields_items (self, iter_values); } =20 +/* Return a sequence of all fields. Each field is a gdb.Field object. + This method is similar to typy_values, except where the supplied=20 + gdb.Type is an array, in which case it returns a list of one entry + which is a gdb.Field object for a range (the array bounds). */ + +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + struct type *type =3D ((type_object *) self)->type; + PyObject *r, *rl; +=20=20 + if (TYPE_CODE (type) !=3D TYPE_CODE_ARRAY) + return typy_fields_items (self, iter_values); + + /* Array type. Handle this as a special case because the common + machinery wants struct or union or enum types. Build a list of + one entry which is the range for the array. */ + r =3D convert_field (type, 0); + if (r =3D=3D NULL) + return NULL; +=20=20 + rl =3D Py_BuildValue ("[O]", r); + if (rl =3D=3D NULL) + { + Py_DECREF (r); + } + + return rl; +} + /* Return a sequence of all field names. Each field is a gdb.Field object= . */ =20 static PyObject * @@ -350,6 +380,48 @@ return type_to_type_object (check_typedef (type)); } =20 +/* Strip typedefs and pointers/reference from a type. Then check that + it is a struct, union, or enum type. If not, raise TypeError. */ + +static struct type * +typy_get_composite (struct type *type) +{ + volatile struct gdb_exception except; + + for (;;) + { + TRY_CATCH (except, RETURN_MASK_ALL) + { + CHECK_TYPEDEF (type); + } + /* Don't use GDB_PY_HANDLE_EXCEPTION here because that returns + a (NULL) pointer of the wrong type. */ + if (except.reason < 0) + { + gdbpy_convert_exception (except); + return NULL; + } + + if (TYPE_CODE (type) !=3D TYPE_CODE_PTR + && TYPE_CODE (type) !=3D TYPE_CODE_REF) + break; + type =3D TYPE_TARGET_TYPE (type); + } + + /* If this is not a struct, union, or enum type, raise TypeError + exception. */ + if (TYPE_CODE (type) !=3D TYPE_CODE_STRUCT=20 + && TYPE_CODE (type) !=3D TYPE_CODE_UNION + && TYPE_CODE (type) !=3D TYPE_CODE_ENUM) + { + PyErr_SetString (PyExc_TypeError, + "Type is not a structure, union, or enum type."); + return NULL; + } +=20=20 + return type; +} + /* Return an array type. */ =20 static PyObject * @@ -1124,9 +1196,23 @@ { struct type *type =3D ((type_object *) self)->type; =20 + type =3D typy_get_composite (type); + if (type =3D=3D NULL) + return -1; + return TYPE_NFIELDS (type); } =20 +/* Implements boolean evaluation of gdb.Type. Handle this like other + Python objects that don't have a meaningful truth value -- all=20 + values are true. */ + +static int +typy_nonzero (PyObject *self) +{ + return 1; +} + /* Return a gdb.Field object for the field named by the argument. */ =20 static PyObject * @@ -1145,20 +1231,10 @@ using lookup_struct_elt_type, portions of that function are copied here. */ =20 - for (;;) - { - TRY_CATCH (except, RETURN_MASK_ALL) - { - CHECK_TYPEDEF (type); - } - GDB_PY_HANDLE_EXCEPTION (except); - - if (TYPE_CODE (type) !=3D TYPE_CODE_PTR - && TYPE_CODE (type) !=3D TYPE_CODE_REF) - break; - type =3D TYPE_TARGET_TYPE (type); - } - + type =3D typy_get_composite (type); + if (type =3D=3D NULL) + return NULL; +=20=20 for (i =3D 0; i < TYPE_NFIELDS (type); i++) { char *t_field_name =3D TYPE_FIELD_NAME (type, i); @@ -1216,18 +1292,9 @@ using lookup_struct_elt_type, portions of that function are copied here. */ =20 - for (;;) - { - TRY_CATCH (except, RETURN_MASK_ALL) - { - CHECK_TYPEDEF (type); - } - GDB_PY_HANDLE_EXCEPTION (except); - if (TYPE_CODE (type) !=3D TYPE_CODE_PTR - && TYPE_CODE (type) !=3D TYPE_CODE_REF) - break; - type =3D TYPE_TARGET_TYPE (type); - } + type =3D typy_get_composite (type); + if (type =3D=3D NULL) + return NULL; =20 for (i =3D 0; i < TYPE_NFIELDS (type); i++) { @@ -1246,6 +1313,10 @@ { typy_iterator_object *typy_iter_obj; =20 + /* Check that "self" is a structure or union type. */ + if (typy_get_composite (((type_object *) self)->type) =3D=3D NULL) + return NULL; +=20=20 typy_iter_obj =3D PyObject_New (typy_iterator_object, &type_iterator_object_type); if (typy_iter_obj =3D=3D NULL) @@ -1489,7 +1560,7 @@ { "unqualified", typy_unqualified, METH_NOARGS, "unqualified () -> Type\n\ Return a variant of this type without const or volatile attributes." }, - { "values", typy_fields, METH_NOARGS, + { "values", typy_values, METH_NOARGS, "values () -> list\n\ Return a list holding all the fields of this type.\n\ Each field is a gdb.Field object." }, @@ -1499,6 +1570,32 @@ { NULL } }; =20 +static PyNumberMethods type_object_as_number =3D { + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_divide */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + typy_nonzero, /* nb_nonzero */ + NULL, /* nb_invert */ + NULL, /* nb_lshift */ + NULL, /* nb_rshift */ + NULL, /* nb_and */ + NULL, /* nb_xor */ + NULL, /* nb_or */ + NULL, /* nb_coerce */ + NULL, /* nb_int */ + NULL, /* nb_long */ + NULL, /* nb_float */ + NULL, /* nb_oct */ + NULL /* nb_hex */ +}; + static PyMappingMethods typy_mapping =3D { typy_length, typy_getitem, @@ -1518,7 +1615,7 @@ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ - 0, /*tp_as_number*/ + &type_object_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ &typy_mapping, /*tp_as_mapping*/ 0, /*tp_hash */ Index: gdb/testsuite/gdb.python/py-type.exp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-type.exp,v retrieving revision 1.14 diff -u -r1.14 py-type.exp --- gdb/testsuite/gdb.python/py-type.exp 28 Sep 2011 20:06:01 -0000 1.14 +++ gdb/testsuite/gdb.python/py-type.exp 9 Nov 2011 17:36:13 -0000 @@ -93,6 +93,16 @@ gdb_test "python print \[(n, v.bitpos) for (n, v) in st.type.items()\]= " {\[\('a', 0L\), \('b', 32L\)\]} "Check fields items list" gdb_test "python print 'a' in st.type" "True" "Check field name exists t= est" gdb_test "python print 'nosuch' in st.type" "False" "Check field name no= nexists test" + gdb_test "python print not not st.type" "True" "Check conversion to bool" + + # Test rejection of mapping operations on scalar types + gdb_test "python print len (st.type\['a'\].type)" "TypeError: Type is no= t a structure, union, or enum type.*" + gdb_test "python print st.type\['a'\].type.has_key ('x')" "TypeError: Ty= pe is not a structure, union, or enum type.*" + gdb_test "python print st.type\['a'\].type.keys ()" "TypeError: Type is = not a structure, union, or enum type.*" + gdb_test "python print st.type\['a'\].type\['x'\]" "TypeError: Type is n= ot a structure, union, or enum type.*" + + # Test conversion to bool on scalar types + gdb_test "python print not not st.type\['a'\].type" "True" =20=20=20 # Test regression PR python/10805 gdb_py_test_silent_cmd "print ar" "print value" 1