Bug 41874 - Incorrect "dereferencing type-punned pointer will break strict-aliasing rules" warning
Summary: Incorrect "dereferencing type-punned pointer will break strict-aliasing rules...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.1
: P3 normal
Target Milestone: 7.0
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2009-10-30 01:32 UTC by Jeffrey Yasskin
Modified: 2022-12-03 22:03 UTC (History)
13 users (show)

See Also:
Host:
Target:
Build:
Known to work: 7.5.0
Known to fail: 4.5.0, 6.5.0
Last reconfirmed: 2009-11-06 09:09:42


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jeffrey Yasskin 2009-10-30 01:32:34 UTC
$ cat test.cc
#include <new>
struct APInt {
    int i;
};
int main() {
    APInt I;
    char Data[sizeof(APInt)];
    new((void*)Data)APInt();
    *(APInt*)Data = I;
}
$ g++ -O3 -Wstrict-aliasing test.cc -o /dev/null
test.cc: In function 'int main()':
test.cc:9: warning: dereferencing type-punned pointer will break strict-aliasing rules
test.cc:9: warning: dereferencing type-punned pointer will break strict-aliasing rules

$ g++ -v
Using built-in specs.
Target: i386-apple-darwin9
Configured with: ../gcc-4.4.1/configure --prefix=/opt/local --build=i386-apple-darwin9 --enable-languages=c,c++,objc,obj-c++,java,fortran --libdir=/opt/local/lib/gcc44 --includedir=/opt/local/include/gcc44 --infodir=/opt/local/share/info --mandir=/opt/local/share/man --with-local-prefix=/opt/local --with-system-zlib --disable-nls --program-suffix=-mp-4.4 --with-gxx-include-dir=/opt/local/include/gcc44/c++/ --with-gmp=/opt/local --with-mpfr=/opt/local
Thread model: posix
gcc version 4.4.1 (GCC) 


The warning goes away if I change "*(APInt*)Data = I;" to "*(APInt*)(void*)Data = I;" even though an extra cast through void* can't improve the situation wrt strict-aliasing.
Comment 1 Andrew Pinski 2009-11-06 09:09:42 UTC
4.5 also fails and I cannot figure why if I do:
#include <new>
struct APInt {
    int i;
};
int main() {
    APInt I;
    void *d;
    char Data[sizeof(APInt)];
    new((void*)Data)APInt();
    d = Data;
    *(APInt*)d = I;
}

GCC does not warn.
Comment 2 rguenther@suse.de 2009-11-06 09:16:01 UTC
Subject: Re:  Incorrect "dereferencing type-punned pointer
 will break strict-aliasing rules" warning

On Fri, 6 Nov 2009, pinskia at gcc dot gnu dot org wrote:

> ------- Comment #1 from pinskia at gcc dot gnu dot org  2009-11-06 09:09 -------
> 4.5 also fails and I cannot figure why if I do:

"fails"?

> #include <new>
> struct APInt {
>     int i;
> };
> int main() {
>     APInt I;
>     void *d;
>     char Data[sizeof(APInt)];
>     new((void*)Data)APInt();
>     d = Data;
>     *(APInt*)d = I;
> }
> 
> GCC does not warn.

Of course not - the code is perfectly valid (apart from Data
not having suitable alignment for APInt, but that's unrelated
to aliasing issues).

Richard.
Comment 3 Andrew Pinski 2009-11-06 09:18:56 UTC
> > ------- Comment #1 from pinskia at gcc dot gnu dot org  2009-11-06 09:09 -------
> > 4.5 also fails 

Fails in that it warns still.

The first example warns with 4.5, while adding an extra variable and doing a cast to void* causes GCC not to warn.  
Comment 4 Richard Biener 2009-11-06 09:20:12 UTC
Btw, this warning is emitted from the frontend which only warns if it sees
the address of an object casted, not random pointers (because of the
many false positives).  The frontend code also has no idea of the concept
of a dynamic type.
Comment 5 Florian Weimer 2010-01-31 09:38:00 UTC
Isn't this a wrong-code bug?  Or is the information used for the diagnostic not used by the optimizers?
Comment 6 Richard Biener 2010-01-31 11:17:51 UTC
(In reply to comment #5)
> Isn't this a wrong-code bug?  Or is the information used for the diagnostic not
> used by the optimizers?

The diagnostics are independent on the optimizers, the one diagnostic that
isn't (that is emitted from the optimizer itself) causes the optimizer to
not optimize (well, because it saw the problem and thus there is no point
in breaking things just because we can).

The general problem is that alias analysis is hard, thus follows that proper
warnings are equally hard.  All warnings we emit are either possible false
positives or if they are not the optimizers will not miscompile your code
because they know there is an alias even though type-based analysis says
there is not (well, this is exactly the case you want to warn about, but
as analysis is hard once you can tell you can as well not exploit the
mis-optimization opportunity).
Comment 7 Ilya Murav'jov 2010-10-05 00:10:20 UTC
AFAIK, users of Boost.Function suffer from this PR too.
https://svn.boost.org/trac/boost/ticket/4538
Comment 8 Florian Weimer 2010-10-05 04:48:54 UTC
(In reply to comment #6)

> The general problem is that alias analysis is hard, thus follows that proper
> warnings are equally hard.

Note that it says "will break strict-aliasing rules", not "might break strict-aliasing rules" (which also exists). I think the user can reasonably expect that the "will break" variant is actually true.
Comment 9 Ilya Murav'jov 2010-10-06 19:43:30 UTC
I've come across another weird warning emission in g++ 4.4:

$ cat test.cc
#include <new>
struct interface_type {

    virtual interface_type* clone(void* storage) const
    {
        return ::new (storage) interface_type();
    }
};

struct poly_base {

    poly_base(const interface_type& x) { x.clone(data); }

    typedef char storage_t[100];
    storage_t data;
};

struct instance_t: interface_type {};

int main()
{
    instance_t pi;
    poly_base p1(pi);

    interface_type* ptr = (interface_type*)(p1.data);
    poly_base p2(*ptr);
}
$ g++ -O3 -Wstrict-aliasing test.cc -o /dev/null
test.cc: In function ‘int main()’:
test.cc:12: warning: dereferencing pointer ‘ptr’ does break strict-aliasing rules
test.cc:25: note: initialized from here

$ g++ -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --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 --enable-linker-build-id --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-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9)

I get this only in g++ 4.4, g++ 4.5 does not warn.

I want to note that this is a different type of warning about strict-aliasing rules, likely a more serious one. Can anyone tell what a difference between
"warning: dereferencing type-punned pointer will break strict-aliasing rules" and "warning: dereferencing pointer ‘ptr’ does break strict-aliasing rules"?
Comment 10 rguenther@suse.de 2010-10-06 20:56:56 UTC
On Wed, 6 Oct 2010, muravev at yandex dot ru wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41874
> 
> --- Comment #9 from Ilya Murav'jov <muravev at yandex dot ru> 2010-10-06 19:43:30 UTC ---
> I've come across another weird warning emission in g++ 4.4:
> 
> $ cat test.cc
> #include <new>
> struct interface_type {
> 
>     virtual interface_type* clone(void* storage) const
>     {
>         return ::new (storage) interface_type();
>     }
> };
> 
> struct poly_base {
> 
>     poly_base(const interface_type& x) { x.clone(data); }
> 
>     typedef char storage_t[100];
>     storage_t data;
> };
> 
> struct instance_t: interface_type {};
> 
> int main()
> {
>     instance_t pi;
>     poly_base p1(pi);
> 
>     interface_type* ptr = (interface_type*)(p1.data);
>     poly_base p2(*ptr);
> }
> $ g++ -O3 -Wstrict-aliasing test.cc -o /dev/null
> test.cc: In function ‘int main()’:
> test.cc:12: warning: dereferencing pointer ‘ptr’ does break strict-aliasing
> rules
> test.cc:25: note: initialized from here
> 
> $ g++ -v
> Using built-in specs.
> Target: i486-linux-gnu
> Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9'
> --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 --enable-linker-build-id --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-objc-gc
> --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic
> --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu
> --target=i486-linux-gnu
> Thread model: posix
> gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9)
> 
> I get this only in g++ 4.4, g++ 4.5 does not warn.
> 
> I want to note that this is a different type of warning about strict-aliasing
> rules, likely a more serious one. Can anyone tell what a difference between
> "warning: dereferencing type-punned pointer will break strict-aliasing rules"
> and "warning: dereferencing pointer ‘ptr’ does break strict-aliasing rules"?

The latter means that when doing pointer analysis GCC pruned all 
pointed-to objects using TBAA so the pointer ended up pointing to
nothing (but still was dereferenced).  The good news for you is that
GCC will assume the pointer points to anything in that case, not
nothing.

In GCC 4.5 points-to analysis doesn't use TBAA to prune the sets anymore
(because its fundamentally wrong), so the code emitting the warning
was removed.

Richard.
Comment 11 Paolo Carlini 2012-10-15 09:27:13 UTC
Richard, is this still an issue?
Comment 12 Richard Biener 2012-10-15 09:45:11 UTC
No, the warning is gone from all releases that are still maintained.
Comment 13 Aso Renji 2017-12-23 15:45:58 UTC
Still have same problem in g++ 6.3.0. So, please reopen this bug.
Comment 14 Jonathan Wakely 2017-12-24 08:21:37 UTC
(In reply to Aso Renji from comment #13)
> Still have same problem in g++ 6.3.0. So, please reopen this bug.

What do you mean by "same problem"? The original testcase does not produce a warning with GCC 6.3.0

If you get a warning for a different piece of code then please open a new bug, this one is fixed.
Comment 15 Aso Renji 2017-12-24 09:24:54 UTC
(In reply to Jonathan Wakely from comment #14)
> What do you mean by "same problem"? The original testcase does not produce a warning with GCC 6.3.0
No, this warning still appear if (and only if) you use -O2 or -O3 optimization key (as it be in startpost with "g++ -O3 -Wstrict-aliasing test.cc -o /dev/null" line).

If I don't use any optimization - yes, this warning don't appeared.
Comment 16 Jonathan Wakely 2017-12-24 10:56:10 UTC
(In reply to Richard Biener from comment #12)
> No, the warning is gone from all releases that are still maintained.

Looks like this wasn't true.
Comment 17 Jason Merrill 2022-12-03 22:03:23 UTC
(In reply to Aso Renji from comment #15)
> No, this warning still appear if (and only if) you use -O2 or -O3
> optimization key (as it be in startpost with "g++ -O3 -Wstrict-aliasing
> test.cc -o /dev/null" line).

I don't see this with any compiler after 6.5.0.