https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70074
Bug ID: 70074 Summary: [C++14] Wrong array write access in constexpr evaluation Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: olegendo at gcc dot gnu.org Target Milestone: --- The the following program compiled with 'g++ -std=c++14 -O2 -Wall' prints: table0: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 table1: 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15 table2: 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15 ... which is a silent wrong-code bug. The numbers of all tables should be the same. I ran into this with gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2). I haven't checked with trunk or newer version of GCC 5. #include <iostream> #include <array> #include <utility> template <typename T, size_t N, size_t... I> constexpr inline std::array<T, N> make_array_1 (const T (&chr)[N], std::index_sequence<I...>) { return {{ (chr[I])... }}; } template <typename T, size_t N> constexpr inline std::array<T, N> make_array (const T (&chr)[N]) { return make_array_1 (chr, std::make_index_sequence<N> ()); } template < unsigned int N, typename T > constexpr inline T reverse_bits (T val) { T out = 0; for (unsigned int i = 0; i < N; ++i) if (val & (T (1) << i)) out |= T (1) << (N - i - 1); return out; } // -------------------------------------------------------------------------- constexpr inline std::array<unsigned int, 16> make_table_0 (void) { unsigned int result[16] = { }; for (unsigned int i = 0; i < 16; ++i) result[reverse_bits<4> (i) & 15] = i; return make_array (result); } inline std::array<unsigned int, 16> make_table_1 (void) { unsigned int result[16] = { }; for (unsigned int i = 0; i < 16; ++i) result[reverse_bits<4> (i) & 15] = i; return make_array (result); } constexpr inline std::array<unsigned int, 16> make_table_2 (void) { unsigned int result[16] = { }; for (unsigned int i = 0; i < 16; ++i) result[i] = i; unsigned int tmp[16] = { }; for (unsigned int i = 0; i < 16; ++i) tmp[i] = result[i]; for (unsigned int i = 0; i < 16; ++i) result[i] = tmp[reverse_bits<4> (i) & 15]; return make_array (result); } static const auto table0 = make_table_0 (); static const auto table1 = make_table_1 (); static const auto table2 = make_table_2 (); int main (void) { std::cout << "table0: "; for (auto&& x : table0) std::cout << x << " "; std::cout << std::endl; std::cout << "table1: "; for (auto&& x : table1) std::cout << x << " "; std::cout << std::endl; std::cout << "table2: "; for (auto&& x : table2) std::cout << x << " "; std::cout << std::endl; return 0; }