Bug 39891

Summary: Bogus location given for warning, no warning at real location: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules
Product: gcc Reporter: Török Edwin <edwin+bugs>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: gcc-bugs, manu, musiphil, rguenth
Priority: P3 Keywords: diagnostic
Version: 4.4.0   
Target Milestone: ---   
Host: x86_64-linux-gnu Target: x86_64-linux-gnu
Build: x86_64-linux-gnu Known to work:
Known to fail: Last reconfirmed: 2009-04-25 10:41:02
Attachments: testcase

Description Török Edwin 2009-04-25 09:37:22 UTC
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)
Comment 1 Török Edwin 2009-04-25 09:39:19 UTC
Created attachment 17690 [details]
testcase
Comment 2 Richard Biener 2009-04-25 10:41:02 UTC
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.
Comment 3 Richard Biener 2009-04-25 11:13:50 UTC
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 ...
Comment 4 Manuel López-Ibáñez 2009-04-29 13:16:53 UTC
(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.
Comment 5 Manuel López-Ibáñez 2009-07-08 13:25:14 UTC
(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.