[move] GCC bug and aliasing questions

Hi, Yesterday I started using Boost.Move in my project. On gcc I had the same problem like the guys here: http://lists.boost.org/Archives/boost/2011/07/184263.php Namely, I can't define the move constructor nor the assignment operators outside my class... After some time I managed to create a minimal example (19 lines) and sent a bug report to the gcc guys: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53725 So far, so good. In the minimizing process I found something interesting: the problem vanishes if I remove the __may_alias__ attribute from the rv<> class. This got me thinking. Do we need this attribute at all? The problematic expression is this: (It's in macros normally placed inside a class, TYPE is the name of this class.) operator ::boost::rv<TYPE>&() { return *static_cast< ::boost::rv<TYPE>*> (this); } But rv<TYPE> is derived from TYPE so to me it looks like the two type is compatible, therefore the code didn't violate the strict aliasing rules, so the attribute is not necessary. (BTW can we violate the strict aliasing rules trough static_cast if we don't do any chained conversion trough void*?) On the other hand, if it's really breaks the rules then we solved the problem for gcc, but we still have undefined behavior on every other compiler. Can we fix this somehow? Cheers, tr3w

On Wed, Jun 20, 2012 at 10:54 AM, Tr3wory <tr3w@freemail.hu> wrote:
Hi,
Yesterday I started using Boost.Move in my project. On gcc I had the same problem like the guys here: http://lists.boost.org/Archives/boost/2011/07/184263.php
Namely, I can't define the move constructor nor the assignment operators outside my class... After some time I managed to create a minimal example (19 lines) and sent a bug report to the gcc guys: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53725
So far, so good.
In the minimizing process I found something interesting: the problem vanishes if I remove the __may_alias__ attribute from the rv<> class. This got me thinking. Do we need this attribute at all?
The problematic expression is this: (It's in macros normally placed inside a class, TYPE is the name of this class.) operator ::boost::rv<TYPE>&() { return *static_cast< ::boost::rv<TYPE>*> (this); }
But rv<TYPE> is derived from TYPE so to me it looks like the two type is compatible, therefore the code didn't violate the strict aliasing rules, so the attribute is not necessary. (BTW can we violate the strict aliasing rules trough static_cast if we don't do any chained conversion trough void*?)
On the other hand, if it's really breaks the rules then we solved the problem for gcc, but we still have undefined behavior on every other compiler.
Can we fix this somehow?
I don't know, but +1 for bringing up this issue; there was another GCC bug I filed not long ago involving the __may_alias__ attribute: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53421 I'm leaning toward agreeing with you on the strict aliasing question but I'm no expert :( - Jeff

El 20/06/2012 19:54, Tr3wory escribió:
But rv<TYPE> is derived from TYPE so to me it looks like the two type is compatible, therefore the code didn't violate the strict aliasing rules, so the attribute is not necessary. (BTW can we violate the strict aliasing rules trough static_cast if we don't do any chained conversion trough void*?)
It might not break strict aliasing (I'm not an expert) but it is undefined behavior to static_cast down a hierarchy to a type that isn't actually the type of the object. Boost.Move uses this undefined behavior hole and the GCC behavior is fixed with may_alias. I haven't found a better solution.
On the other hand, if it's really breaks the rules then we solved the problem for gcc, but we still have undefined behavior on every other compiler.
It's undefined behavior in GCC also.
Can we fix this somehow?
I haven't found a better alternative. Ion

On Thu, Jun 21, 2012 at 9:46 PM, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
El 20/06/2012 19:54, Tr3wory escribió:
But rv<TYPE> is derived from TYPE so to me it looks like the two type is compatible, therefore the code didn't violate the strict aliasing rules, so the attribute is not necessary. (BTW can we violate the strict aliasing rules trough static_cast if we don't do any chained conversion trough void*?)
It might not break strict aliasing (I'm not an expert) but it is undefined behavior to static_cast down a hierarchy to a type that isn't actually the type of the object. Boost.Move uses this undefined behavior hole and the GCC behavior is fixed with may_alias. I haven't found a better solution.
So if I understand you correctly, we are in the field of undefined behavior either way. Did you experience any problem with gcc what you solved with may_alias, or it's just the materialization of the idea of "better safe than sorry"? tr3w

El 21/06/2012 22:56, Tr3wory escribió:
So if I understand you correctly, we are in the field of undefined behavior either way. Did you experience any problem with gcc what you solved with may_alias, or it's just the materialization of the idea of "better safe than sorry"?
Yes, there was problems with modern GCC and aggresive optimizations, which may_alias solved. Ion

Thanks for the information. And for the library. :) It looks like we need to live with this gcc bug then... tr3w On Fri, Jun 22, 2012 at 9:43 PM, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
El 21/06/2012 22:56, Tr3wory escribió:
So if I understand you correctly, we are in the field of undefined behavior either way. Did you experience any problem with gcc what you solved with may_alias, or it's just the materialization of the idea of "better safe than sorry"?
Yes, there was problems with modern GCC and aggresive optimizations, which may_alias solved.
Ion
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (3)
-
Ion Gaztañaga
-
Jeffrey Lee Hellrung, Jr.
-
Tr3wory