summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen W. Taylor <otaylor@fishsoup.net>2010-09-14 14:17:35 -0400
committerOwen W. Taylor <otaylor@fishsoup.net>2010-11-01 16:38:51 -0400
commit29ec4294d9232dcfd7cfec4e20c0e302a5ff3e80 (patch)
tree437ac2231d1d9d618ee0fa69e14b2c8426699e95
parente4eef4fe4a35161907ab353515ec7aa6a31c282b (diff)
downloadgobject-introspection-29ec4294d9232dcfd7cfec4e20c0e302a5ff3e80.tar.gz
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
-rw-r--r--girepository/giroffsets.c86
1 files 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 <string.h>
/* 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);
}