Avoid triggering strict-aliasing checks when iterating preferences

Rewrite the code to iterate generically over Meta*Preference
arrays to avoid running into GCC's strict-aliasing warnings.

https://bugzilla.gnome.org/show_bug.cgi?id=615672
This commit is contained in:
Owen W. Taylor 2010-04-13 14:40:31 -04:00
parent a78373f324
commit 9915a18810

View File

@ -232,15 +232,9 @@ static GConfEnumStringPair symtab_titlebar_action[] =
};
/*
* This structure represents the common parts at the front of all
* the preferences structures; there are some additional places
* it could be used in addition to where it is currently.
* Note that 'gchar *key' is the first element of all these structures;
* we count on that below in key_is_used and do_override.
*/
typedef struct
{
gchar *key;
MetaPreference pref;
} MetaGenericPreference;
/*
* The details of one preference which is constrained to be
@ -1115,41 +1109,51 @@ meta_prefs_init (void)
init_workspace_names ();
}
/* This count on the key being the first element of the
* preference structure */
static gboolean
key_is_used (MetaGenericPreference *prefs,
size_t pref_size,
const char *new_key)
key_is_used (void *prefs,
size_t pref_size,
const char *new_key)
{
MetaGenericPreference *p;
void *p = prefs;
for (p = prefs;
p->key != NULL;
p = (MetaGenericPreference *)((guchar *)p + pref_size))
while (TRUE)
{
if (strcmp (p->key, new_key) == 0)
char **key = p;
if (*key == NULL)
break;
if (strcmp (*key, new_key) == 0)
return TRUE;
p = (guchar *)p + pref_size;
}
return FALSE;
}
static gboolean
do_override (MetaGenericPreference *prefs,
size_t pref_size,
const char *search_key,
char *new_key)
do_override (void *prefs,
size_t pref_size,
const char *search_key,
char *new_key)
{
MetaGenericPreference *p;
void *p = prefs;
for (p = prefs;
p->key != NULL;
p = (MetaGenericPreference *)((guchar *)p + pref_size))
while (TRUE)
{
if (strcmp (p->key, search_key) == 0)
char **key = p;
if (*key == NULL)
break;
if (strcmp (*key, search_key) == 0)
{
p->key = new_key;
*key = new_key;
return TRUE;
}
p = (guchar *)p + pref_size;
}
return FALSE;
@ -1190,10 +1194,10 @@ meta_prefs_override_preference_location (const char *original_key,
/* We depend on a unique mapping from GConf key to preference, so
* enforce this */
if (key_is_used ((MetaGenericPreference *)preferences_enum, sizeof(MetaEnumPreference), new_key) ||
key_is_used ((MetaGenericPreference *)preferences_bool, sizeof(MetaBoolPreference), new_key) ||
key_is_used ((MetaGenericPreference *)preferences_string, sizeof(MetaStringPreference), new_key) ||
key_is_used ((MetaGenericPreference *)preferences_int, sizeof(MetaIntPreference), new_key))
if (key_is_used (preferences_enum, sizeof(MetaEnumPreference), new_key) ||
key_is_used (preferences_bool, sizeof(MetaBoolPreference), new_key) ||
key_is_used (preferences_string, sizeof(MetaStringPreference), new_key) ||
key_is_used (preferences_int, sizeof(MetaIntPreference), new_key))
{
meta_warning (_("GConf key %s is already in use and can't be used to override %s\n"),
new_key, original_key);
@ -1216,10 +1220,10 @@ meta_prefs_override_preference_location (const char *original_key,
}
found =
do_override ((MetaGenericPreference *)preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
do_override ((MetaGenericPreference *)preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
do_override ((MetaGenericPreference *)preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
do_override ((MetaGenericPreference *)preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
do_override (preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
do_override (preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
do_override (preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
do_override (preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
if (found)
{
if (overridden)