* GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules”
@ 2017-04-30 21:56 Freddie Chopin
2017-05-02 10:17 ` Richard Biener
0 siblings, 1 reply; 3+ messages in thread
From: Freddie Chopin @ 2017-04-30 21:56 UTC (permalink / raw)
To: gcc
Hello!
A code that I wrote was warning-free in GCC 4.9, GCC 5 and GCC 6. It
was also warning-free with some older GCC 7 experimental snapshots (for
example 7-20170409). But in the most recent snapshot (including the
first RC), it started to produce a warning about aliasing. The code
basically boils down to this:
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
#include <type_traits>
std::aligned_storage<sizeof(int), alignof(int)>::type storage;
int main()
{
    *reinterpret_cast<int*>(&storage) = 42;
}
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
Compilation with latest GCC 7 RC:
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
$ g++ -Wall -O2 -c main.cpp
main.cpp: In function 'int main()':
main.cpp:7:34: warning: dereferencing type-punned pointer will break
strict-aliasing rules [-Wstrict-aliasing]
 *reinterpret_cast<int*>(&storage) = 42;
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
(interesting observation is that the warning is not produced when
optimizations are disabled)
Compilation with GCC 6 gives no warnings at all.
Now I'm wondering, the code above definitely HAS type-punning, no
question about that, but isn't std::aligned_storage meant to be used
that way?
For instance the example code given here on cppreference generally
produces no warning with GCC 7 but only because:
- std::string somehow is not affected,
- std::aligned_storage is accessed with an offset.
http://en.cppreference.com/w/cpp/types/aligned_storage
By changing std::string into int, removing offset access to
std::aligned_storage and removing irrelevant parts you get this:
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
#include <iostream>
#include <type_traits>
#include <string>
template<class T, std::size_t N>
class static_vector
{
    // properly aligned uninitialized storage for N T's
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
    std::size_t m_size = 0;
public:
    // Access an object in aligned storage
    const T& operator[](std::size_t pos) const
    {
        return *reinterpret_cast<const T*>(data/*+pos*/); // <- note
here, offset access disabled
    }
};
int main()
{
    static_vector<int, 10> v1;
    std::cout << v1[0] << '\n' << v1[1] << '\n';
}
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
And this produces exactly the same warning:
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
main.cpp: In instantiation of 'const T& static_vector<T,
N>::operator[](std::size_t) const [with T = int; unsigned int N = 10;
std::size_t = unsigned int]':
main.cpp:24:22:Â Â Â required from here
main.cpp:17:16: warning: dereferencing type-punned pointer will break
strict-aliasing rules [-Wstrict-aliasing]
         return *reinterpret_cast<const T*>(data/*+pos*/);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
So my question is - is this a bug or a feature?
Thanks in advance!
Regards,
FCh
BTW - I've also posted this question on stackoverflow
http://stackoverflow.com/questions/43711567/gcc-7-aligned-storage-and-dereferencing-type-punned-pointer-will-break-strict
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules”
2017-04-30 21:56 GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules” Freddie Chopin
@ 2017-05-02 10:17 ` Richard Biener
2017-05-02 10:35 ` Freddie Chopin
0 siblings, 1 reply; 3+ messages in thread
From: Richard Biener @ 2017-05-02 10:17 UTC (permalink / raw)
To: Freddie Chopin; +Cc: GCC Development
On Sun, Apr 30, 2017 at 11:56 PM, Freddie Chopin <freddie_chopin@op.pl> wrote:
> Hello!
>
> A code that I wrote was warning-free in GCC 4.9, GCC 5 and GCC 6. It
> was also warning-free with some older GCC 7 experimental snapshots (for
> example 7-20170409). But in the most recent snapshot (including the
> first RC), it started to produce a warning about aliasing. The code
> basically boils down to this:
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> #include <type_traits>
>
> std::aligned_storage<sizeof(int), alignof(int)>::type storage;
>
> int main()
> {
> *reinterpret_cast<int*>(&storage) = 42;
> }
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> Compilation with latest GCC 7 RC:
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> $ g++ -Wall -O2 -c main.cpp
> main.cpp: In function 'int main()':
> main.cpp:7:34: warning: dereferencing type-punned pointer will break
> strict-aliasing rules [-Wstrict-aliasing]
> *reinterpret_cast<int*>(&storage) = 42;
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> (interesting observation is that the warning is not produced when
> optimizations are disabled)
>
> Compilation with GCC 6 gives no warnings at all.
>
> Now I'm wondering, the code above definitely HAS type-punning, no
> question about that, but isn't std::aligned_storage meant to be used
> that way?
>
> For instance the example code given here on cppreference generally
> produces no warning with GCC 7 but only because:
> - std::string somehow is not affected,
> - std::aligned_storage is accessed with an offset.
>
> http://en.cppreference.com/w/cpp/types/aligned_storage
>
> By changing std::string into int, removing offset access to
> std::aligned_storage and removing irrelevant parts you get this:
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> #include <iostream>
> #include <type_traits>
> #include <string>
>
> template<class T, std::size_t N>
> class static_vector
> {
> // properly aligned uninitialized storage for N T's
> typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
> std::size_t m_size = 0;
>
> public:
>
> // Access an object in aligned storage
> const T& operator[](std::size_t pos) const
> {
> return *reinterpret_cast<const T*>(data/*+pos*/); // <- note
> here, offset access disabled
> }
> };
>
> int main()
> {
> static_vector<int, 10> v1;
> std::cout << v1[0] << '\n' << v1[1] << '\n';
> }
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> And this produces exactly the same warning:
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> main.cpp: In instantiation of 'const T& static_vector<T,
> N>::operator[](std::size_t) const [with T = int; unsigned int N = 10;
> std::size_t = unsigned int]':
> main.cpp:24:22: required from here
> main.cpp:17:16: warning: dereferencing type-punned pointer will break
> strict-aliasing rules [-Wstrict-aliasing]
> return *reinterpret_cast<const T*>(data/*+pos*/);
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --
>
> So my question is - is this a bug or a feature?
First of all the -Wstrict-aliasing warning is not very accurate. But this shows
an issue with GCC 7 so please open a bugreport. Testcase without libstd++
headers:
template<unsigned _Len, unsigned _Align>
struct aligned_storage
{
union type
{
unsigned char __data[_Len];
struct __attribute__((__aligned__((_Align)))) { } __align;
};
};
aligned_storage<sizeof(int), alignof(int)>::type storage;
int main()
{
*reinterpret_cast<int*>(&storage) = 42;
}
and we warn from
525 && (set1 == 0
526 || (!alias_set_subset_of (set2, set1)
527 && !alias_sets_conflict_p (set1, set2))))
528 {
529 warning (OPT_Wstrict_aliasing, "dereferencing
type-punned "
530 "pointer will break strict-aliasing rules");
531 return true;
where set1 == 0 (of 'storage') and set2 == 1 (of 'int'). Not sure why we warn
if set1 == 0 ...
Richard.
> Thanks in advance!
>
> Regards,
> FCh
>
> BTW - I've also posted this question on stackoverflow
> http://stackoverflow.com/questions/43711567/gcc-7-aligned-storage-and-dereferencing-type-punned-pointer-will-break-strict
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-05-02 10:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-30 21:56 GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules” Freddie Chopin
2017-05-02 10:17 ` Richard Biener
2017-05-02 10:35 ` Freddie Chopin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).