Bug 38486 - Missing warning about type punning
Summary: Missing warning about type punning
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.3.2
: P3 enhancement
Target Milestone: ---
Assignee: Richard Biener
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2008-12-11 12:56 UTC by dominik.strasser
Modified: 2009-05-20 15:15 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2009-04-27 15:18:42


Attachments
Source code which illustrates the problem. (335 bytes, text/plain)
2008-12-11 12:57 UTC, dominik.strasser
Details

Note You need to log in before you can comment on or make changes to this bug.
Description dominik.strasser 2008-12-11 12:56:03 UTC
When compiling the attached source code with -Wall -O3 -UWARN, no warning on type punning is printed.
If I compile with -Wall -O3 -DWARN, a warning is printed.
ff.C:31: warning: dereferencing type-punned pointer will break strict-aliasing rules

While in the attached example, everything seems to work fine, my application crashes.

Would it be feasible to print the warning also for the nested function calls ?
Comment 1 dominik.strasser 2008-12-11 12:57:04 UTC
Created attachment 16884 [details]
Source code which illustrates the problem.
Comment 2 Richard Biener 2008-12-11 13:16:35 UTC
The complication is that we "optimize" the code into a form that no longer
violates aliasing rules which effectively disables the warning that happens
after inlining.  IMHO we can issue alias warnings from the code that
propagates (const struct Func &) &D.1753 into *D.1793_4 (tree forwprop) if
and if only the propagation result is a VIEW_CONVERT_EXPR and its base object
does not contain a pointer dereference.  In turn further propagations of
invariant addresses into that VIEW_CONVERT_EXPR may then raise the warning
instead.

Note that this is really a middle-end issue, IMHO the FE based warnings should
be disabled if optimization is enabled as they warn on conversions and not
pointer dereferences thus giving too many false positives anyway.
Comment 3 Andrew Pinski 2008-12-12 00:20:34 UTC
This is what I get for trying to get better optimizations in the first place :).  Maybe we should warn when we do the VCE conversion if the aliasing sets don't match?
Comment 4 Richard Biener 2008-12-12 10:11:32 UTC
Yes.  Though you have to be careful not to create false positives for

float f;
struct X { int i; };

struct X *p = (struct X *)&f;
float *q = (float *)&p->i;
return *q;

if the code is obfuscated enough that the definition of p is not visible.
Or, one could even say that creating VIEW_CONVERT_EXPR <float> (p->i) is
an invalid transformation and causes an alias violation.  Do we do this
transformation in this case?  I think we should avoid doing it here
(that is, whenever the expression we view-convert contains a pointer
dereference).
Comment 5 Andrew Pinski 2008-12-20 18:53:43 UTC
(In reply to comment #4)
> Yes.  Though you have to be careful not to create false positives for
> 
> float f;
> struct X { int i; };
> 
> struct X *p = (struct X *)&f;
> float *q = (float *)&p->i;
> return *q;

Actually that is an aliasing violation still as you still accessing *p, yes it looks like it is not an access because of the address but you are still accessing *p really.
Comment 6 Andrew Pinski 2008-12-20 18:58:07 UTC
(In reply to comment #5)
> Actually that is an aliasing violation still as you still accessing *p, yes it
> looks like it is not an access because of the address but you are still
> accessing *p really.

Oh and we do create a VCE for that case already:
  return VIEW_CONVERT_EXPR<int>(a->a);

Yes we thought about this when I was writing the original code which created the VCE.  If it was just (float*)p, there would be no aliasing violation but the access happens even if memory is not really accessed.  The address expression still does not cause no access to happen, this is why doing (int)(&((struct f*)(0))->a) is still undefined code as there is an access to a NULL pointer (even if we supported this access).
Comment 7 Richard Biener 2008-12-29 18:05:45 UTC
Even if I cannot find the proper section of the standard that says &a->b is
not considered an access it does make sense for GIMPLE to do so.  Otherwise
we cannot transform (char *)a + 4 to &a->b because the latter would be a
(possibly invalid) access while the former is not.

So, we definitely should _not_ generate a V_C_E here.
Comment 8 dominik.strasser 2009-04-27 15:12:35 UTC
Are there any news on this guy here ?
I am really having a hard time porting my project to GCC 4.3 as I have a big source file which seems to do a lot of type punning, but I get no warnings. Depending on the compile options I get crashes. Or should I just turn off strict aliasing for this source file to be on the safe side.
Comment 9 Richard Biener 2009-04-27 15:18:42 UTC
Mine.
Comment 10 Richard Biener 2009-05-20 15:15:41 UTC
Note that I am going to fix the missing warning because of comment #2 only.
For 4.3 comment #2 does not apply, instead you get a warning with -Wstrict-aliasing=1

g++-4.3 -Wall -O3 -S t.C -UWARN -fdump-tree-all -Wstrict-aliasing=1
t.C: In function ‘Term term(const Func&)’:
t.C:13: warning: dereferencing type-punned pointer might break strict-aliasing rules
t.C: In function ‘const Func& func(const Term&)’:
t.C:23: warning: dereferencing type-punned pointer might break strict-aliasing rules