Merge branch 'wip/smcv/type-signedness-followup' into 'main'

Improve handling of standard types' signedness

See merge request GNOME/glib!4095
This commit is contained in:
Philip Withnall 2024-06-04 16:45:35 +00:00
commit 2ab34d97f7
5 changed files with 75 additions and 26 deletions

View File

@ -657,11 +657,11 @@ register_internal (GIRepository *repository,
Header *header;
const char *namespace;
g_return_val_if_fail (typelib != NULL, FALSE);
g_return_val_if_fail (typelib != NULL, NULL);
header = (Header *)typelib->data;
g_return_val_if_fail (header != NULL, FALSE);
g_return_val_if_fail (header != NULL, NULL);
namespace = gi_typelib_get_string (typelib, header->namespace);
@ -1907,7 +1907,7 @@ require_internal (GIRepository *repository,
char *tmp_version = NULL;
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
g_return_val_if_fail (namespace != NULL, FALSE);
g_return_val_if_fail (namespace != NULL, NULL);
typelib = get_registered_status (repository, namespace, version, allow_lazy,
&is_lazy, &version_conflict);

View File

@ -28,6 +28,7 @@
#include "girnode-private.h"
#include "gitypelib-internal.h"
#include "glib-private.h"
#include <stdlib.h>
#include <string.h>
@ -451,30 +452,24 @@ typedef struct {
unsigned int is_signed : 1;
} IntegerAliasInfo;
/*
* signedness:
* @T: a numeric type
*
* Returns: 1 if @T is signed, 0 if it is unsigned
*/
#define signedness(T) (((T) -1) <= 0)
G_STATIC_ASSERT (signedness (int) == 1);
G_STATIC_ASSERT (signedness (unsigned int) == 0);
static IntegerAliasInfo integer_aliases[] = {
{ "gchar", sizeof (gchar), 1 },
{ "guchar", sizeof (guchar), 0 },
{ "gshort", sizeof (gshort), 1 },
{ "gushort", sizeof (gushort), 0 },
{ "gint", sizeof (gint), 1 },
{ "guint", sizeof (guint), 0 },
{ "glong", sizeof (glong), 1 },
{ "gulong", sizeof (gulong), 0 },
{ "gssize", sizeof (gssize), 1 },
{ "gsize", sizeof (gsize), 0 },
{ "gintptr", sizeof (gintptr), 1 },
{ "guintptr", sizeof (guintptr), 0 },
#define INTEGER_ALIAS(T) { #T, sizeof (T), signedness (T) }
/* It is platform-dependent whether gchar is signed or unsigned, but
* GObject-Introspection has traditionally treated it as signed,
* so continue to hard-code that instead of using INTEGER_ALIAS */
{ "gchar", sizeof (gchar), 1 },
#define INTEGER_ALIAS(T) { #T, sizeof (T), G_SIGNEDNESS_OF (T) }
INTEGER_ALIAS (guchar),
INTEGER_ALIAS (gshort),
INTEGER_ALIAS (gushort),
INTEGER_ALIAS (gint),
INTEGER_ALIAS (guint),
INTEGER_ALIAS (glong),
INTEGER_ALIAS (gulong),
INTEGER_ALIAS (gssize),
INTEGER_ALIAS (gsize),
INTEGER_ALIAS (gintptr),
INTEGER_ALIAS (guintptr),
INTEGER_ALIAS (off_t),
INTEGER_ALIAS (time_t),
#ifdef G_OS_UNIX

View File

@ -22,6 +22,7 @@
#include "config.h"
#include "glib-init.h"
#include "glib-private.h"
#include "gmacros.h"
#include "gtypes.h"
#include "gutils.h" /* for GDebugKey */
@ -42,6 +43,10 @@
/* This seems as good a place as any to make static assertions about platform
* assumptions we make throughout GLib. */
/* Test that private macro G_SIGNEDNESS_OF() works as intended */
G_STATIC_ASSERT (G_SIGNEDNESS_OF (int) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (unsigned int) == 0);
/* We do not support 36-bit bytes or other historical curiosities. */
G_STATIC_ASSERT (CHAR_BIT == 8);
@ -77,6 +82,11 @@ G_STATIC_ASSERT (G_ALIGNOF (TestInt) == G_ALIGNOF (int));
G_STATIC_ASSERT (sizeof (gchar) == 1);
G_STATIC_ASSERT (sizeof (guchar) == 1);
/* It is platform-dependent whether gchar is signed or unsigned, so there
* is no assertion here for it */
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guchar) == 0);
G_STATIC_ASSERT (sizeof (gint8) * CHAR_BIT == 8);
G_STATIC_ASSERT (sizeof (guint8) * CHAR_BIT == 8);
G_STATIC_ASSERT (sizeof (gint16) * CHAR_BIT == 16);
@ -95,12 +105,16 @@ G_STATIC_ASSERT (G_MINSHORT == SHRT_MIN);
G_STATIC_ASSERT (G_MAXSHORT == SHRT_MAX);
G_STATIC_ASSERT (sizeof (unsigned short) == sizeof (gushort));
G_STATIC_ASSERT (G_MAXUSHORT == USHRT_MAX);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gshort) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gushort) == 0);
G_STATIC_ASSERT (sizeof (int) == sizeof (gint));
G_STATIC_ASSERT (G_MININT == INT_MIN);
G_STATIC_ASSERT (G_MAXINT == INT_MAX);
G_STATIC_ASSERT (sizeof (unsigned int) == sizeof (guint));
G_STATIC_ASSERT (G_MAXUINT == UINT_MAX);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint) == 0);
G_STATIC_ASSERT (sizeof (long) == GLIB_SIZEOF_LONG);
G_STATIC_ASSERT (sizeof (long) == sizeof (glong));
@ -108,6 +122,8 @@ G_STATIC_ASSERT (G_MINLONG == LONG_MIN);
G_STATIC_ASSERT (G_MAXLONG == LONG_MAX);
G_STATIC_ASSERT (sizeof (unsigned long) == sizeof (gulong));
G_STATIC_ASSERT (G_MAXULONG == ULONG_MAX);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (glong) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gulong) == 0);
G_STATIC_ASSERT (G_HAVE_GINT64 == 1);
@ -127,6 +143,10 @@ G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (size_t));
* However, we do not assume that GPOINTER_TO_SIZE can store an arbitrary
* pointer in a gsize (known to be false on CHERI). */
G_STATIC_ASSERT (sizeof (size_t) <= sizeof (void *));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (size_t) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gsize) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gssize) == 1);
/* Standard C does not guarantee that size_t is the same as uintptr_t,
* but GLib currently assumes they are the same: see
* <https://gitlab.gnome.org/GNOME/glib/-/issues/2842>.
@ -139,10 +159,13 @@ G_STATIC_ASSERT (sizeof (size_t) <= sizeof (void *));
G_STATIC_ASSERT (sizeof (size_t) == sizeof (uintptr_t));
G_STATIC_ASSERT (G_ALIGNOF (size_t) == G_ALIGNOF (uintptr_t));
#endif
/* goffset is always 64-bit, even if off_t is only 32-bit
* (compiling without large-file-support on 32-bit) */
G_STATIC_ASSERT (sizeof (goffset) == sizeof (gint64));
G_STATIC_ASSERT (G_ALIGNOF (goffset) == G_ALIGNOF (gint64));
/* goffset is always signed */
G_STATIC_ASSERT (G_SIGNEDNESS_OF (goffset) == 1);
G_STATIC_ASSERT (sizeof (gfloat) == sizeof (float));
G_STATIC_ASSERT (G_ALIGNOF (gfloat) == G_ALIGNOF (float));
@ -153,26 +176,44 @@ G_STATIC_ASSERT (sizeof (gintptr) == sizeof (intptr_t));
G_STATIC_ASSERT (sizeof (guintptr) == sizeof (uintptr_t));
G_STATIC_ASSERT (G_ALIGNOF (gintptr) == G_ALIGNOF (intptr_t));
G_STATIC_ASSERT (G_ALIGNOF (guintptr) == G_ALIGNOF (uintptr_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gintptr) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guintptr) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (intptr_t) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (uintptr_t) == 0);
G_STATIC_ASSERT (sizeof (gint8) == sizeof (int8_t));
G_STATIC_ASSERT (sizeof (guint8) == sizeof (uint8_t));
G_STATIC_ASSERT (G_ALIGNOF (gint8) == G_ALIGNOF (int8_t));
G_STATIC_ASSERT (G_ALIGNOF (guint8) == G_ALIGNOF (uint8_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint8) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint8) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (int8_t) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint8_t) == 0);
G_STATIC_ASSERT (sizeof (gint16) == sizeof (int16_t));
G_STATIC_ASSERT (sizeof (guint16) == sizeof (uint16_t));
G_STATIC_ASSERT (G_ALIGNOF (gint16) == G_ALIGNOF (int16_t));
G_STATIC_ASSERT (G_ALIGNOF (guint16) == G_ALIGNOF (uint16_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (int16_t) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint16_t) == 0);
G_STATIC_ASSERT (sizeof (gint32) == sizeof (int32_t));
G_STATIC_ASSERT (sizeof (guint32) == sizeof (uint32_t));
G_STATIC_ASSERT (G_ALIGNOF (gint32) == G_ALIGNOF (int32_t));
G_STATIC_ASSERT (G_ALIGNOF (guint32) == G_ALIGNOF (uint32_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint32) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint32) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (int32_t) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint32_t) == 0);
G_STATIC_ASSERT (sizeof (gint64) == sizeof (int64_t));
G_STATIC_ASSERT (sizeof (guint64) == sizeof (uint64_t));
G_STATIC_ASSERT (G_ALIGNOF (gint64) == G_ALIGNOF (int64_t));
G_STATIC_ASSERT (G_ALIGNOF (guint64) == G_ALIGNOF (uint64_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint64) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint64) == 0);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (int64_t) == 1);
G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint64_t) == 0);
/**
* g_mem_gc_friendly:

View File

@ -25,6 +25,16 @@
#include "gstdioprivate.h"
#include "gdatasetprivate.h"
/*
* G_SIGNEDNESS_OF:
* @T: a numeric type such as `unsigned int`
*
* An integer constant expression indicating whether @T is a signed type.
*
* Returns: 1 if @T is signed, 0 if it is unsigned
*/
#define G_SIGNEDNESS_OF(T) (((T) -1) <= 0)
/* gcc defines __SANITIZE_ADDRESS__, clang sets the address_sanitizer
* feature flag.
*

View File

@ -38,6 +38,7 @@
#include "config.h"
#include "glib-private.h"
#include "glib-unix.h"
#include "glib-unixprivate.h"
#include "gmain-internal.h"
@ -66,9 +67,11 @@
G_STATIC_ASSERT (sizeof (ssize_t) == GLIB_SIZEOF_SSIZE_T);
G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
G_STATIC_ASSERT (G_SIGNEDNESS_OF (ssize_t) == 1);
G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
/* It's platform-dependent whether pid_t is signed, so no assertion */
/* If this assertion fails, then the ABI of g_unix_open_pipe() would be
* ambiguous on this platform.