This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules”
- From: Freddie Chopin <freddie_chopin at op dot pl>
- To: gcc at gcc dot gnu dot org
- Date: Sun, 30 Apr 2017 23:56:09 +0200
- Subject: GCC 7, aligned_storage and “dereferencing type-punned pointer will break strict-aliasing rules”
- Authentication-results: sourceware.org; auth=none
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