GNOME Bugzilla – Bug 608137
Build warning with G_ATOMIC_OP_MEMORY_BARRIER_NEEDED and -Wcast-qual
Last modified: 2011-05-28 21:01:47 UTC
when I build a my code, it prompt: cc1: warnings being treated as errors In file included from /usr/include/glib-2.0/glib/gasyncqueue.h:34, from /usr/include/glib-2.0/glib.h:34, from pils.c:34: /usr/include/glib-2.0/glib/gthread.h: In function 'g_once_init_enter': /usr/include/glib-2.0/glib/gthread.h:344: error: cast discards qualifiers from pointer target type In /usr/include/glib-2.0/glib/gatomic.h you'll find. -------------------------------------------------- #ifndef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED ... # define g_atomic_pointer_get(atomic) ((gpointer)*(atomic)) ... #else ... # define g_atomic_pointer_get(atomic) \ ((void) sizeof (gchar [sizeof (*(atomic)) == sizeof (gpointer) ? 1 : -1]), \ (g_atomic_pointer_get) ((volatile gpointer G_GNUC_MAY_ALIAS *) (void *) (atomic))) ... #endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ -------------------------------------------------- so in /usr/include/glib-2.0/glib/gthread.h the g_once_init_enter expand: -------------------------------------------------- static __inline __attribute__ ((unused)) gboolean g_once_init_enter (volatile gsize *value_location) { if ((gpointer) ((void) sizeof (gchar [sizeof (*(value_location)) == sizeof (gpointer) ? 1 : -1]), (g_atomic_pointer_get) ((volatile gpointer __attribute__((may_alias)) *) (void *) (value_location))) != ((void *)0)) return (0); else return g_once_init_enter_impl (value_location); } -------------------------------------------------- When I delete the "(void *) " in if statement, like "(void *) (value_location)", it builds okay.
Created attachment 152297 [details] [review] The patch for dismiss the warning of "cast discards qualifiers from pointer target type" I'm not sure if it's reasonable, but it fix my issue.
My glib2's version: 2.22.1, from below demo, you can reproduce it. $ cat gchar.c #include <glib.h> #include <glib/gthread.h> #include <stdio.h> int main(int argc, char **agrv) { int j = 0, k = 1; int a = sizeof (gchar [j > k ? 1 : -1]); //int b = sizeof (gchar [-1]); int b = 0; printf ("%d, %d\n", a, b); return 0; } $ gcc -Wcast-qual -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -DG_ATOMIC_OP_MEMORY_BARRIER_NEEDED -lglib-2.0 -o gchar gchar.c In file included from /usr/include/glib-2.0/glib/gasyncqueue.h:34, from /usr/include/glib-2.0/glib.h:34, from gchar.c:19: /usr/include/glib-2.0/glib/gthread.h: In function ‘g_once_init_enter’: /usr/include/glib-2.0/glib/gthread.h:344: warning: cast discards qualifiers from pointer target type
-Wcast-qual is tricky. That's why it's not in -Wall or even -Wextra. I'm pretty sure your patch will introduce new warnings if you compile with "-O2 -Wall" though. (Or more specifically, "-fstrict-aliasing -Wstrict-aliasing".) I'm not sure it's possible to make this compile with both -Wcast-qual AND -Wstrict-aliasing. (Note that because this involves code in the header files, the problem applies not just to glib itself, but to anything that calls g_once_init_enter(), so it basically means that glib prevents its consumers from using -Wcast-qual.) (see bug 600315 for a similar problem)
Dan, Thanks! And do you know when's G_ATOMIC_OP_MEMORY_BARRIER_NEEDED was defined? I found in ppc, ppc64 and ia64 it was defined. Any idea?
it's defined by configure, on architectures that need a memory barrier in atomic operations
*** Bug 624561 has been marked as a duplicate of this bug. ***
Created attachment 168581 [details] [review] A cleaner patch, with the correct cast
I can confirm the problem. The current code in the .h affects any program including glib.h, not allowing the use of -Wcast-qual; so I consider it significant (it affects user code, it's not just awarning that can be disabled on the glib build) The macro for g_atomic_pointer_get is assumed to be a replacement (in some cases) and call to the g_atomic_pointer_get function (not macro) which is declared as taking a pointer to a volatile value. So passing a pointer-to-volatile to it should be valid. However the current code casts the argument to (void *), which is technically an invalid cast. The cast should be to (volatile void *); if the argument is volatile it produces no warning (and fixes the original problem), and if the argument isn't volatile it is harmless, because anyway the value will be converted to a pointer to volatile when doing the argument passing. The original patch removing the (void *) cast may be problematic because depending on the type of the argument, the other cast (volatile gpointer G_GNUC_MAY_ALIAS *) could be invalid.
I've just noted that my patch is missing a similar change in g_atomic_pointer_set.
I think this bug is obsolete now; after a recent rewrite of the atomic operations.