GNOME Bugzilla – Bug 90400
GFundamentalTypes still 32bit on 64bit system
Last modified: 2011-02-04 16:10:07 UTC
On pa64 systems GType is defined as gulong and is 64 bits long. Functions such as gtk_signal_new with variable arguments takes GType arguments. This works fine if G_TYPE_BOOLEAN is used, since that is defined as (GType) (5 << 3), which is treated correctly as a 64bit long. However, GTK_TYPE_BOOL is part of an enumeration, and by default, enum values are 32 bits, so when used it is used as variable argument, gcc (3.1.1 and 3.2.0-20020807) both treat it as a 32 bit int. Unfortunately, gtk_signal_new treats all varargs as 64bits, and hence gets it picks up two 32bit arguments. The GType code treats this as a pointer and segmentation faults occur. For example, signals[MOVE_CURSOR] = gtk_signal_new ("move_cursor", GTK_RUN_LAST | GTK_RUN_ACTION, GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkLabelClass, move_cursor), _gtk_marshal_VOID__ENUM_INT_BOOLEAN, GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL); GTK_TYPE_INT and GTK_TYPE_BOOL are treated as 32 bit ints rather than 64 bit longs. To further complicate things, the PA64 ABI treats the first 8 arguments as registers, so things work correctly, simply because although store word into a register will automatically extend the value to a 64 bit value. The one solution I can think of without excessive recoding (ie, explicitly casting every vararg argument) is to turn the enum into #defines. Another possiblity (which looks like works on gcc, but I have only tested by a small test program and looking at the RTL output) is the following. typedef enum /*< skip >*/ { GTK_TYPE_INVALID = G_TYPE_INVALID, GTK_TYPE_NONE = G_TYPE_NONE, GTK_TYPE_ENUM = G_TYPE_ENUM, GTK_TYPE_FLAGS = G_TYPE_FLAGS, /* GtkArg types */ GTK_TYPE_CHAR = G_TYPE_CHAR, GTK_TYPE_UCHAR = G_TYPE_UCHAR, GTK_TYPE_BOOL = G_TYPE_BOOLEAN, GTK_TYPE_INT = G_TYPE_INT, GTK_TYPE_UINT = G_TYPE_UINT, GTK_TYPE_LONG = G_TYPE_LONG, GTK_TYPE_ULONG = G_TYPE_ULONG, GTK_TYPE_FLOAT = G_TYPE_FLOAT, GTK_TYPE_DOUBLE = G_TYPE_DOUBLE, GTK_TYPE_STRING = G_TYPE_STRING, GTK_TYPE_BOXED = G_TYPE_BOXED, GTK_TYPE_POINTER = G_TYPE_POINTER, GTK_HACK = ULONG_MAX } GtkFundamentalType; There may be some compiler flags, but it all looks ugly. Many thanks Ross Alexander
Doing it with #defines is write. GTK_SIGNAL_* are just compatibility wrappers for for G_SIGNAL_* which are already #defines for this reason. We shoudlswitch to #define GTK_TYPE_BOOL G_TYPE_BOOLEAN. etc. I don't think there are any potential API/ABI pitfalls from making this change ... on 64-bit bit (and especially 64-bit big endian) it is broken currently, so ABI compat doesn't matter. On 32-bit platforms, there are no ABI issues. For API issues, C doesn't distinguish enums from integer constants in any strong way. I guess you could have a C++ function that took GFundementalType as an argument, causing problems when passing a GTP_TYPE_BOOLEAN to it, but it seems like an unlikely construct. Plus, people should hav ebeen using GTK_TYPE_* as constants of type GType, not of GFundementalType.
*** Bug 94052 has been marked as a duplicate of this bug. ***
Sun Sep 29 12:59:42 2002 Manish Singh <yosh@gimp.org> * gtk/gtktypeutils.h: use #defines instead of enum for GtkFundamentalType compat, to prevent 64-bit vs. 32-bit confusion (#90400)