On Sun, Apr 30, 2017 at 11:56 PM, Freddie Chopin <freddie_cho...@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