From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23363 invoked by alias); 9 Nov 2011 00:29:39 -0000 Received: (qmail 23340 invoked by uid 22791); 9 Nov 2011 00:29:25 -0000 X-SWARE-Spam-Status: No, hits=-3.9 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_LOW,RP_MATCHES_RCVD,TW_IV X-Spam-Check-By: sourceware.org Received: from mail-qw0-f41.google.com (HELO mail-qw0-f41.google.com) (209.85.216.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Nov 2011 00:29:10 +0000 Received: by qadc11 with SMTP id c11so1264582qad.0 for ; Tue, 08 Nov 2011 16:29:09 -0800 (PST) Received: by 10.224.183.15 with SMTP id ce15mr77611qab.42.1320798549301; Tue, 08 Nov 2011 16:29:09 -0800 (PST) MIME-Version: 1.0 Received: by 10.224.183.15 with SMTP id ce15mr77583qab.42.1320798548620; Tue, 08 Nov 2011 16:29:08 -0800 (PST) Received: by 10.224.6.76 with HTTP; Tue, 8 Nov 2011 16:29:08 -0800 (PST) In-Reply-To: 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> Date: Wed, 09 Nov 2011 00:29:00 -0000 Message-ID: Subject: Re: [RFA] Python: raise exception on field-related gdb.Type methods if it's not struct or union From: Doug Evans To: Paul Koning Cc: Eli Zaretskii , tromey@redhat.com, gdb-patches@sourceware.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-System-Of-Record: true X-IsSubscribed: yes 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/msg00213.txt.bz2 On Tue, Nov 8, 2011 at 1:40 PM, Paul Koning wrote: > > On Nov 5, 2011, at 5:04 PM, Doug Evans wrote: > >> On Sat, Nov 5, 2011 at 7:36 AM, Paul Koning wro= te: >>>> Maybe I'd be happy if gdb.Type (and maybe gdb.Value) were simply more >>>> rigorous in throwing exceptions for invalid cases. >>> >>> I agree. =A0I'll put that together. >> >> Sounds great if it's possible. >> >> I don't know enough about the C Python API, but when I tried a simple >> hack to have len(scalar_type) throw an exception "not scalar_type" >> started throwing exceptions too. =A0:-( =A0See PyObject_IsTrue. > > I found the answer to that question with a bit of searching. =A0 Attached= is a patch that raises an exception (TypeError) for len() and all the fiel= d reference methods if the type isn't struct or union. I wasn't sure using as_number here was kosher. "works for me" if it does the job. > Does this need new testcases? Yeah, I think so. Verify "not type" DTRT, and affected operations on scalar types flag the right error. One question I have is: for struct types that have an empty field list (say an empty struct), what's the result of "not type". True or False? I can argue either way, and I'm not sure what's the best answer, long term. [But then again, my python fu isn't enough to be comfortable with any conclusion I reach.] Thanks very much for doing this! btw, a couple of nits: 1) Please put a blank line between a function's comment and its definition. There are several occurrences of this. 2) Can you rename typy_deref? typy_get_struct works for me, I'm sure there's a better name. "deref" feels confusing, one can deref a pointer to anything, not just structs/unions, and the function doesn't necessarily do a dereference. > =A0 =A0 =A0 =A0paul > > ChangeLog: > > 2011-11-08 =A0Paul Koning =A0 > > =A0 =A0 =A0 =A0* python/py-type.c (typy_deref): New function. > =A0 =A0 =A0 =A0(typy_nonzero): New function. > =A0 =A0 =A0 =A0(typy_length): Raise exception if not struct or union type. > =A0 =A0 =A0 =A0(typy_getitem): Ditto. > =A0 =A0 =A0 =A0(typy_has_key): Ditto. > =A0 =A0 =A0 =A0(typy_make_iter): Ditto. > > Index: 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 -p -r1.28 py-type.c > --- python/py-type.c =A0 =A04 Nov 2011 11:57:04 -0000 =A0 =A0 =A0 1.28 > +++ python/py-type.c =A0 =A08 Nov 2011 21:36:40 -0000 > @@ -350,6 +350,45 @@ typy_strip_typedefs (PyObject *self, PyO > =A0 return type_to_type_object (check_typedef (type)); > =A0} > > +/* Strip typedefs and pointers/reference from a type. =A0Then check that > + =A0 it is a struct or union type. =A0If not, raise TypeError. =A0*/ > +static struct type * > +typy_deref (struct type *type) > +{ > + =A0volatile struct gdb_exception except; > + > + =A0for (;;) > + =A0 =A0{ > + =A0 =A0 =A0TRY_CATCH (except, RETURN_MASK_ALL) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 CHECK_TYPEDEF (type); > + =A0 =A0 =A0 } > + =A0 =A0 =A0/* Don't use GDB_PY_HANDLE_EXCEPTION here because that retur= ns > + =A0 =A0 =A0 =A0a (NULL) pointer of the wrong type. =A0*/ > + =A0 =A0 =A0if (except.reason < 0) > + =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 gdbpy_convert_exception (except); > + =A0 =A0 =A0 =A0 return NULL; > + =A0 =A0 =A0 } > + > + =A0 =A0 =A0if (TYPE_CODE (type) !=3D TYPE_CODE_PTR > + =A0 =A0 =A0 =A0 && TYPE_CODE (type) !=3D TYPE_CODE_REF) > + =A0 =A0 =A0 break; > + =A0 =A0 =A0type =3D TYPE_TARGET_TYPE (type); > + =A0 =A0} > + > + =A0/* If this is not a struct or union type, raise TypeError exception.= =A0*/ > + =A0if (TYPE_CODE (type) !=3D TYPE_CODE_STRUCT > + =A0 =A0 =A0&& TYPE_CODE (type) !=3D TYPE_CODE_UNION) > + =A0 =A0{ > + =A0 =A0 =A0PyErr_SetString (PyExc_TypeError, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"Type is not a structure or = union type."); > + =A0 =A0 =A0return NULL; > + =A0 =A0} > + > + =A0return type; > +} > + > =A0/* Return an array type. =A0*/ > > =A0static PyObject * > @@ -1124,9 +1163,22 @@ typy_length (PyObject *self) > =A0{ > =A0 struct type *type =3D ((type_object *) self)->type; > > + =A0type =3D typy_deref (type); > + =A0if (type =3D=3D NULL) > + =A0 =A0return -1; > + > =A0 return TYPE_NFIELDS (type); > =A0} > > +/* Implements boolean evaluation of gdb.Type. =A0Handle this like other > + =A0 Python objects that don't have a meaningful truth value -- all > + =A0 values are true. =A0*/ > +static int > +typy_nonzero (PyObject *self) > +{ > + =A0return 1; > +} > + > =A0/* Return a gdb.Field object for the field named by the argument. =A0*/ > > =A0static PyObject * > @@ -1145,20 +1197,10 @@ typy_getitem (PyObject *self, PyObject * > =A0 =A0 =A0using lookup_struct_elt_type, portions of that function are > =A0 =A0 =A0copied here. =A0*/ > > - =A0for (;;) > - =A0 =A0{ > - =A0 =A0 =A0TRY_CATCH (except, RETURN_MASK_ALL) > - =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 CHECK_TYPEDEF (type); > - =A0 =A0 =A0 } > - =A0 =A0 =A0GDB_PY_HANDLE_EXCEPTION (except); > - > - =A0 =A0 =A0if (TYPE_CODE (type) !=3D TYPE_CODE_PTR > - =A0 =A0 =A0 =A0 && TYPE_CODE (type) !=3D TYPE_CODE_REF) > - =A0 =A0 =A0 break; > - =A0 =A0 =A0type =3D TYPE_TARGET_TYPE (type); > - =A0 =A0} > - > + =A0type =3D typy_deref (type); > + =A0if (type =3D=3D NULL) > + =A0 =A0return NULL; > + > =A0 for (i =3D 0; i < TYPE_NFIELDS (type); i++) > =A0 =A0 { > =A0 =A0 =A0 char *t_field_name =3D TYPE_FIELD_NAME (type, i); > @@ -1216,18 +1258,9 @@ typy_has_key (PyObject *self, PyObject * > =A0 =A0 =A0using lookup_struct_elt_type, portions of that function are > =A0 =A0 =A0copied here. =A0*/ > > - =A0for (;;) > - =A0 =A0{ > - =A0 =A0 =A0TRY_CATCH (except, RETURN_MASK_ALL) > - =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 CHECK_TYPEDEF (type); > - =A0 =A0 =A0 } > - =A0 =A0 =A0GDB_PY_HANDLE_EXCEPTION (except); > - =A0 =A0 =A0if (TYPE_CODE (type) !=3D TYPE_CODE_PTR > - =A0 =A0 =A0 =A0 && TYPE_CODE (type) !=3D TYPE_CODE_REF) > - =A0 =A0 =A0 break; > - =A0 =A0 =A0type =3D TYPE_TARGET_TYPE (type); > - =A0 =A0} > + =A0type =3D typy_deref (type); > + =A0if (type =3D=3D NULL) > + =A0 =A0return NULL; > > =A0 for (i =3D 0; i < TYPE_NFIELDS (type); i++) > =A0 =A0 { > @@ -1246,6 +1279,10 @@ typy_make_iter (PyObject *self, enum gdb > =A0{ > =A0 typy_iterator_object *typy_iter_obj; > > + =A0/* Check that "self" is a structure or union type. =A0*/ > + =A0if (typy_deref (((type_object *) self)->type) =3D=3D NULL) > + =A0 =A0return NULL; > + > =A0 typy_iter_obj =3D PyObject_New (typy_iterator_object, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&type_iter= ator_object_type); > =A0 if (typy_iter_obj =3D=3D NULL) > @@ -1499,6 +1536,32 @@ Return a volatile variant of this type" > =A0 { NULL } > =A0}; > > +static PyNumberMethods type_object_as_number =3D { > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_add */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_subtract */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_multiply */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_divide */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_remainder */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_divmod */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_power */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_negative */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_positive */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_absolute */ > + =A0typy_nonzero, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* nb_nonze= ro */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_invert */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_lshift */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_rshift */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_and */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_xor */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_or */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_coerce */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_int */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_long */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_float */ > + =A0NULL, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* = nb_oct */ > + =A0NULL =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* nb_hex */ > +}; > + > =A0static PyMappingMethods typy_mapping =3D { > =A0 typy_length, > =A0 typy_getitem, > @@ -1518,7 +1581,7 @@ static PyTypeObject type_object_type =3D > =A0 0, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_setat= tr*/ > =A0 0, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_compa= re*/ > =A0 0, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_repr*/ > - =A00, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_as_n= umber*/ > + =A0&type_object_as_number, =A0 =A0 =A0 =A0/*tp_as_number*/ > =A0 0, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_as_se= quence*/ > =A0 &typy_mapping, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_as_mapping*/ > =A0 0, =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*tp_hash = */ > >