6.5: Expressions7. An object shall have it's stored value accessed only by an lvalue expression
that has one of the following types 61):
61) the intent of this list is to specify those circumstances in which an object may not be aliased.
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
It looks like the way to fix these issues are with temporary variables. I explained this better in a post to desktop-devel-list and gnome-bugsquad:
Subject: Deferencing type-punned pointers, and how to stop gcc giving you a warning
Date: Sun, 25 Apr 2004 19:04:34 +1000
From: xxx (find me on the lists!) <deepcover@nospam.mpx.com.au>
Newsgroups: gmane.comp.gnome.desktopHi all,
I've been looking at a few warnings that gcc have been spitting out at
me lately about "Derefencing type-punned pointer will break
strict-aliasing rules".Here's what the gcc manual has to say about it:
> -fstrict-aliasing Allows the compiler to assume the strictest
> aliasing rules applicable to the language being compiled. For C (and
> C++), this activates optimizations based on the type of expressions.
> In particular, an object of one type is assumed never to reside at
> the same address as an object of a different type, unless the types
> are almost the same. For example, an "unsigned int" can alias an
> "int", but not a "void*" or a "double". A character type may alias
> any other type.
>
> Pay special attention to code like this:
>
> union a_union { int i; double d; };
>
> int f() { a_union t; t.d = 3.0; return t.i; }
>
> The practice of reading from a different union member than the one
> most recently written to (called ``type-punning'') is common. Even
> with -fstrict-aliasing, type-punning is allowed, provided the memory
> is accessed through the union type. So, the code above will work as
> expected. However, this code might not:
>
> int f() { a_union t; int* ip; t.d = 3.0; ip = &t.i; return *ip; }
>
> Every language that wishes to perform language-specific alias
> analysis should define a function that computes, given an "tree"
> node, an alias set for the node. Nodes in different alias sets are
> not allowed to alias. For an example, see the C front-end function
> "c_get_alias_set".
>
> Enabled at levels -O2, -O3, -Os."
>
and
> -Wstrict-aliasing This option is only active when -fstrict-aliasing
> is active. It warns about code which might break the strict aliasing
> rules that the compiler is using for optimization. The warning does
> not catch all cases, but does attempt to catch the more common
> pitfalls. It is included in -Wall.
When I compiled gtk+2.4 (and gtk+2.2) I found that I was getting quite a
few of these warnings. During my discovery of the problem - see
http://bugzilla.gnome.org/show_bug.cgi?id=140722 - I've found some
general rules to try to prevent these warnings:* if you use g_module_symbol, and you need to use a void* function
pointer with multiple parameters to get the module's symbol pointer,
then *also* declare a gpointer pfunc_name, and declare the function
pointer itself to be "void (func_name) (int x, int y)=NULL;" Then, call
g_module_symbol and pass the third parameter as &pfunc_name. As soon as
it's been called, then assign func_name the address of pfunc_name.Example (from gdk-pixbuf/queryloaders.c):
static void
query_module (const char *dir, const char *file)
{
char *path;
GModule *module;// needed or gcc will give a warning that dereferencing
// type-punned pointer will break strict-aliasing rules
gpointer pfill_info;
gpointer pfill_vtable;void (*fill_info) (GdkPixbufFormat *info)=NULL;
void (*fill_vtable) (GdkPixbufModule *module)=NULL;if (g_path_is_absolute (file))
path = g_strdup (file);
else
path = g_build_filename (dir, file, NULL);module = g_module_open (path, 0);
if (module &&
g_module_symbol (module, "fill_info", &pfill_info) &&
g_module_symbol (module, "fill_vtable", &pfill_vtable)) {
GdkPixbufFormat *info;
GdkPixbufModule *vtable;fill_info = pfill_info;
fill_vtable = pfill_vtable;
.
.
.
etcAs far as I can tell, gcc doesn't like casting a function pointer with a
specific parameter signature to a regular gpointer. So you have to pass
an actual gpointer variable's address to g_module_symbol and then copy
over the the gpointer variable's address to the actual function pointer
and THEN call the function pointer.* if you use gdk_window_get_user_data, parameter 2 of this function is a
gpointer*, so again you can't just do something like:
> GtkWidget *widget;
> GdkWindow *window;
>
> gdk_window_get_user_data(window, (gpointer*)&widget);This is because a gpointer * is really void **, and GtkWidget is a
typedef to the structure _GtkWidget. As types, these are obviously
incompatible, however as pointers they're the "same" type (ie and
address to an area of memory)... however gcc it breaks gcc's
strict-aliasing rules. You can't cast a struct pointer to a gpointer*
without the warning (though your program will compile OK), but you can
cast a gpointer* to a GtkWidget*. Therefore, you need to do the following:
> GtkWidget *widget;
> GdkWindow *window;
>
> gpointer pwidget;
>
> gdk_window_get_user_data(window, &pwidget);
> widget = (GtkWidget*) &pwidget;
Obviously, these examples can be applied to other areas where you get
this warning.Anyway, I hope this helps somewhat.
Chris
So far, the bugs I've submitted patches for are:
- Bug 140346: libmoduletestplugin_a.c gives type-punned warning when compiling glibc-2.2.3
- Bug 141011: Unused variable i in gtk_cell_view_cell_layout_clear of gtkcellview.c
- Bug 141020: gtkmain.c: multiple warnings about deferencing type-punned pointer breaks strict aliasing rules
- Bug 141024: gtkselection.c: gtk_selection_convert - warning about deferencing type-punned pointer breaking strict aliasing rules
- Bug 141027: gtktipsquery.c: gtk_tips_query_event - warning about deferencing type-punned pointer breaks strict aliasing rules
- Bug 141030: gtkwidget.c: gtk_widget_reparent_subwindows - warning about deferencing type-punned pointer breaking strict aliasing rules
- Bug 141066: queryimmodules.c: query_module - warning: dereferencing type-punned pointer will break strict-aliasing rules
- Bug 141069: demos/gtk-demo/textview.c: easter_egg_callback -
warning: dereferencing type-punned pointer will break strict-aliasing rules
- Bug 141072: tests/testgtk.c: many warnings fixed
- Bug 141080: Patch to remove multiple warnings in gdk/x11/gdkdnd-x11.c
- Bug 141010: When compiling queryloaders.c gcc generates warning that dereferencing type-punned pointer breaks strict-aliasing
- Bug 141011: Unused variable i in gtk_cell_view_cell_layout_clear of gtkcellview.c
- Bug 141020: gtkmain.c: multiple warnings about deferencing type-punned pointer breaks strict aliasing rules
- Bug 141024: gtkselection.c: gtk_selection_convert - warning about deferencing type-punned pointer breaking strict aliasing rules
- Bug 141027: gtktipsquery.c: gtk_tips_query_event - warning about deferencing type-punned pointer breaks strict aliasing rules
- Bug 141030: gtkwidget.c: gtk_widget_reparent_subwindows - warning about deferencing type-punned pointer breaking strict aliasing rules
And last, but not least:
- Bug 141080: Patch to remove multiple warnings in gdk/x11/gdkdnd-x11.c
This last one deserves a comment. It's probably the ugliest hack job I've seen or done so far. What part of the code tries to do is to cast from a unsigned char ** to a MotifTargetTableHeader*! This, of course, breaks gcc's C99 strict aliasing rules (in fact I wouldn't wonder it breaks a whole lot more too, but let's not go there). To get around this, you need to convert a guchar** (unsigned char**) to a MotifTargetTableHeader*. The only way I can see that is valid is to create a guchar**, use this in parameter 12 of XGetWindowProperty, cast this to a temporary gpointer, and then cast the temporary gpointer to an XGetWindowProperty* variable.
I suspect that Owen Taylor from RedHat won't be too happy with the fix... *sigh* Well, I did at least tell them it was a hack - just check out the diff with my comments!
| < Contest is the enemy | BBC White season: 'Rivers of Blood' > |

Post to Twitter
