Compile attached testcase using: $ g++-4.4 -c -O1 -fstrict-aliasing -Wstrict-aliasing foo.i foo.i: In function ‘bool foo()’: foo.i:8: warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules foo.i:26: note: initialized from here Line 8 has this: 7: APSInt &operator=(const APSInt &RHS) { 8: APInt::operator=(RHS); Line 26 has this: 26: AdditionalOffset = Val.getInt(); None of these violate the strict aliasing rules. The only place that could violate the strict aliasing rules in the testcase is at line 17: 14: void *Data[sizeof(APSInt)]; 15: public: 16: APSInt &getInt() { 17: return *(APSInt*)(void*)Data; g++ 4.3.3 doesn't give any warning, neither does g++ 4.2.4. I think this is a bug because: - the warning is not given at the place that (possibly) violates the strict aliasing rules, but at the place where the pointer obtained by violating the rules is dereferenced. - removing line 26 silences the warning, and no warning given for getInt or operator= anymore Also does the construct at line 17 really violate the aliasing rules? $ g++-4.4 -v Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.0-1~exp1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-objc-gc --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.0 (Debian 4.4.0-1~exp1)
Created attachment 17690 [details] testcase
Thanks for the short testcase. I'll try to improve the location information. The compiler at the point of the warning sees D.1756_5 = (struct APSInt &) &Val.Data; AdditionalOffset.D.1723 = D.1756_5->D.1723; and complains about dereferencing D.1756_5 which is of type APSInt * but the object that is accessed is of type void *. So yes, this is an alias violation. What you probably want to do is sth like class APValue { private: char Data[sizeof(APSInt)]; public: APSInt &getInt() { return *(new (Data) APSInt); } }; to be conforming.
The location is also "correct" in the sense that we try to warn with the location of the _dereference_. And that is indeed in APSInt& APSInt::operator=(const APSInt&): (void) (((struct APSInt *) this)->D.1723 = *(const struct APInt &) &((const struct APSInt *) RHS)->D.1723) the pointer initialization point is that of the call - we dereference a type-pun of the this pointer in Val.getInt(). I have some improvements though - trying to get rid of '<anonymous>' most of the time. The improved version would look like t.ii: In function 'bool foo()': t.ii:8: warning: dereferencing type-punned pointer '& Val.APValue::Data' does break strict-aliasing rules t.ii:26: note: initialized from here I don't know if that is more useful though - the &Val.APValue::Data expression does not appear literally in the program either. Note that getInt is completely inlined and there is no location involving that function available anymore :/ The difficulties of C++ and late diagnostics ...
(In reply to comment #3) > > Note that getInt is completely inlined and there is no location involving > that function available anymore :/ The difficulties of C++ and late > diagnostics ... > I wonder what Clang+LLVM does here. Their diagnostics are (in general) far superior and we are the ones that should start following their lead.
(In reply to comment #3) > > Note that getInt is completely inlined and there is no location involving > that function available anymore :/ The difficulties of C++ and late > diagnostics ... Don't we keep abstract_origin somewhere? I have seen in the middle-end that sometimes we test whether something is an inline variable or not.