From 29ec4294d9232dcfd7cfec4e20c0e302a5ff3e80 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Tue, 14 Sep 2010 14:17:35 -0400 Subject: Compute enumeration storage types more accurately Previously we just were sloppy and didn't bother to accurately compute signed/unsigned for enumeration types. But since we expect bindings to decode a field value or function return value from an integer to an enumeration they have know whether an integer value is 0xffffffff or -1, so we need to do the full computation. https://bugzilla.gnome.org/show_bug.cgi?id=629704 --- girepository/giroffsets.c | 86 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/girepository/giroffsets.c b/girepository/giroffsets.c index bcac716c..94fdc664 100644 --- a/girepository/giroffsets.c +++ b/girepository/giroffsets.c @@ -23,9 +23,9 @@ #include /* The C standard specifies that an enumeration can be any char or any signed - * or unsigned integer type capable of resresenting all the values of the + * or unsigned integer type capable of representing all the values of the * enumeration. We use test enumerations to figure out what choices the - * compiler makes. + * compiler makes. (Ignoring > 32 bit enumerations) */ typedef enum { @@ -52,24 +52,26 @@ typedef enum { ENUM_6 = ((guint)G_MAXINT) + 1 /* compiler could use uint32 */ } Enum6; -/* GIrNodeValue has guint32 values, so if it matters to the ABI whether - * constant values are signed, we are in trouble. And we don't handle - * enums with > 32 bit values. */ - -#if 0 typedef enum { ENUM_7 = -1 /* compiler could use int8, int16, int32 */ } Enum7; -/* etc... */ -#endif +typedef enum { + ENUM_8 = -129 /* compiler could use int16, int32 */ +} Enum8; + +typedef enum { + ENUM_9 = G_MINSHORT - 1 /* compiler could use int32 */ +} Enum9; static void compute_enum_storage_type (GIrNodeEnum *enum_node) { GList *l; - gint32 max_value = 0; + gint64 max_value = 0; + gint64 min_value = 0; int width; + gboolean signed_type; if (enum_node->storage_type != GI_TYPE_TAG_VOID) /* already done */ return; @@ -79,29 +81,63 @@ compute_enum_storage_type (GIrNodeEnum *enum_node) GIrNodeValue *value = l->data; if (value->value > max_value) max_value = value->value; + if (value->value < min_value) + min_value = value->value; } - if (max_value < 128) - width = sizeof (Enum1); - else if (max_value < 256) - width = sizeof (Enum2); - else if (max_value < G_MAXSHORT) - width = sizeof (Enum3); - else if (max_value < G_MAXUSHORT) - width = sizeof (Enum4); - else if (max_value < G_MAXINT) - width = sizeof (Enum5); + if (min_value < 0) + { + signed_type = TRUE; + + if (min_value > -128 && max_value <= 127) + width = sizeof(Enum7); + else if (min_value >= G_MINSHORT && max_value <= G_MAXSHORT) + width = sizeof(Enum8); + else + width = sizeof(Enum9); + } else - width = sizeof (Enum6); + { + if (max_value <= 127) + { + width = sizeof (Enum1); + signed_type = (gint64)(Enum1)(-1) < 0; + } + else if (max_value <= 255) + { + width = sizeof (Enum2); + signed_type = (gint64)(Enum2)(-1) < 0; + } + else if (max_value <= G_MAXSHORT) + { + width = sizeof (Enum3); + signed_type = (gint64)(Enum3)(-1) < 0; + } + else if (max_value <= G_MAXUSHORT) + { + width = sizeof (Enum4); + signed_type = (gint64)(Enum4)(-1) < 0; + } + else if (max_value <= G_MAXINT) + { + width = sizeof (Enum5); + signed_type = (gint64)(Enum5)(-1) < 0; + } + else + { + width = sizeof (Enum6); + signed_type = (gint64)(Enum6)(-1) < 0; + } + } if (width == 1) - enum_node->storage_type = GI_TYPE_TAG_UINT8; + enum_node->storage_type = signed_type ? GI_TYPE_TAG_INT8 : GI_TYPE_TAG_UINT8; else if (width == 2) - enum_node->storage_type = GI_TYPE_TAG_UINT16; + enum_node->storage_type = signed_type ? GI_TYPE_TAG_INT16 : GI_TYPE_TAG_UINT16; else if (width == 4) - enum_node->storage_type = GI_TYPE_TAG_UINT32; + enum_node->storage_type = signed_type ? GI_TYPE_TAG_INT32 : GI_TYPE_TAG_UINT32; else if (width == 8) - enum_node->storage_type = GI_TYPE_TAG_UINT64; + enum_node->storage_type = signed_type ? GI_TYPE_TAG_INT64 : GI_TYPE_TAG_UINT64; else g_error ("Unexpected enum width %d", width); } -- cgit v1.2.1