[Bug c++/84684] inserting random code / flags produces wrong code
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Mar 5 13:24:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84684
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
#include <array>
#include <algorithm>
template <typename alphabet_type>
constexpr char to_char(alphabet_type const alph)
{
return alph.to_char();
}
constexpr const char *check[][3] = {
{ "ACGT", __null, __null },
{ "ACGT", "-", __null },
{ "ACGT", "-", "ACGTN" },
{ "ACGTN", "-", "ACGT" },
{ "-", "ACGT", "ACGTN" } };
template <int idx, typename ...alphabet_types>
struct union_composition
{
static constexpr size_t value_size = (alphabet_types::value_size + ... );
uint8_t _value;
template <size_t fixed_size, typename alphabet_t>
static constexpr auto value_to_char_helper(alphabet_t alphabet)
{
std::array<char, fixed_size> value_to_char{};
for (size_t i = 0u; i < alphabet_t::value_size; ++i) {
value_to_char[i] = to_char(alphabet.assign_rank(i));
}
return value_to_char;
}
static constexpr auto make_value_to_char()
{
constexpr auto N = sizeof...(alphabet_types);
constexpr std::array<size_t, N> alphabet_sizes
{
alphabet_types::value_size...
};
constexpr size_t fixed_size =
std::max({alphabet_types::value_size...});
constexpr std::array value_to_char_tables = std::array<std::array<char,
fixed_size>, N>
{
value_to_char_helper<fixed_size>(alphabet_types{})...
};
std::array<char, value_size> value_to_char{};
static_assert (value_size == (idx == 0 ? 4 : (idx < 2 ? 5 : 10)));
static_assert (N == (idx == 0 ? 1 : (idx < 2 ? 2 : 3)));
static_assert (fixed_size == (idx < 2 ? 4 : 5));
static_assert (alphabet_sizes[0] == __builtin_strlen(check[idx][0]));
if constexpr(idx >= 1)
static_assert (alphabet_sizes[1] == __builtin_strlen(check[idx][1]));
if constexpr (idx >= 2)
static_assert (alphabet_sizes[2] == __builtin_strlen(check[idx][2]));
static_assert (value_to_char_tables[0][0] == check[idx][0][0]);
if constexpr (alphabet_sizes[0] > 1)
static_assert (value_to_char_tables[0][1] == check[idx][0][1]);
if constexpr (alphabet_sizes[0] > 2)
static_assert (value_to_char_tables[0][2] == check[idx][0][2]);
if constexpr (alphabet_sizes[0] > 3)
static_assert (value_to_char_tables[0][3] == check[idx][0][3]);
if constexpr (alphabet_sizes[0] > 4)
static_assert (value_to_char_tables[0][4] == check[idx][0][4]);
if constexpr (idx >= 1) {
static_assert (value_to_char_tables[1][0] == check[idx][1][0]);
if constexpr (alphabet_sizes[1] > 1)
static_assert (value_to_char_tables[1][1] == check[idx][1][1]);
if constexpr (alphabet_sizes[1] > 2)
static_assert (value_to_char_tables[1][2] == check[idx][1][2]);
if constexpr (alphabet_sizes[1] > 3)
static_assert (value_to_char_tables[1][3] == check[idx][1][3]);
if constexpr (alphabet_sizes[1] > 4)
static_assert (value_to_char_tables[1][4] == check[idx][1][4]);
}
if constexpr (idx >= 2) {
static_assert (value_to_char_tables[2][0] == check[idx][2][0]);
if constexpr (alphabet_sizes[2] > 1)
static_assert (value_to_char_tables[2][1] == check[idx][2][1]);
if constexpr (alphabet_sizes[2] > 2)
static_assert (value_to_char_tables[2][2] == check[idx][2][2]);
if constexpr (alphabet_sizes[2] > 3)
static_assert (value_to_char_tables[2][3] == check[idx][2][3]);
if constexpr (alphabet_sizes[2] > 4)
static_assert (value_to_char_tables[2][4] == check[idx][2][4]);
}
for (size_t i = 0u, value = 0u; i < N; ++i)
for (size_t k = 0u; k < alphabet_sizes[i]; ++k, ++value)
value_to_char[value] = value_to_char_tables[i][k];
return value_to_char;
}
};
struct gap
{
constexpr char to_char() const noexcept
{
return '-';
}
constexpr gap & assign_rank([[maybe_unused]] bool const i) noexcept
{
return *this;
}
static constexpr size_t value_size{1};
};
struct dna4
{
constexpr char to_char() const noexcept
{
return value_to_char[_value];
}
constexpr dna4 & assign_rank(uint8_t const c)
{
_value = c;
return *this;
}
static constexpr size_t value_size{4};
static constexpr char value_to_char[value_size] { 'A', 'C', 'G', 'T' };
uint8_t _value;
};
struct dna5
{
constexpr char to_char() const noexcept
{
return value_to_char[_value];
}
constexpr dna5 & assign_rank(uint8_t const c)
{
_value = c;
return *this;
}
static constexpr size_t value_size{5};
static constexpr char value_to_char[value_size] { 'A', 'C', 'G', 'T', 'N'
};
uint8_t _value;
};
constexpr std::array value_to_char1 = union_composition<0,
dna4>::make_value_to_char();
static_assert(value_to_char1.size() == 4u);
static_assert(value_to_char1[0] == 'A');
static_assert(value_to_char1[1] == 'C');
static_assert(value_to_char1[2] == 'G');
static_assert(value_to_char1[3] == 'T');
constexpr std::array value_to_char2 = union_composition<1, dna4,
gap>::make_value_to_char();
static_assert(value_to_char2.size() == 5u);
static_assert(value_to_char2[0] == 'A');
static_assert(value_to_char2[1] == 'C');
static_assert(value_to_char2[2] == 'G');
static_assert(value_to_char2[3] == 'T');
static_assert(value_to_char2[4] == '-');
constexpr std::array value_to_char3 = union_composition<2, dna4, gap,
dna5>::make_value_to_char();
static_assert(value_to_char3.size() == 10u);
static_assert(value_to_char3[0] == 'A');
static_assert(value_to_char3[1] == 'C');
static_assert(value_to_char3[2] == 'G');
static_assert(value_to_char3[3] == 'T');
static_assert(value_to_char3[4] == '-');
static_assert(value_to_char3[5] == 'A');
static_assert(value_to_char3[6] == 'C');
static_assert(value_to_char3[7] == 'G');
static_assert(value_to_char3[8] == 'T');
static_assert(value_to_char3[9] == 'N');
constexpr std::array value_to_char4 = union_composition<3, dna5, gap,
dna4>::make_value_to_char();
static_assert(value_to_char4.size() == 10u);
static_assert(value_to_char4[0] == 'A');
static_assert(value_to_char4[1] == 'C');
static_assert(value_to_char4[2] == 'G');
static_assert(value_to_char4[3] == 'T');
static_assert(value_to_char4[4] == 'N');
static_assert(value_to_char4[5] == '-');
static_assert(value_to_char4[6] == 'A');
static_assert(value_to_char4[7] == 'C');
static_assert(value_to_char4[8] == 'G');
static_assert(value_to_char4[9] == 'T');
constexpr std::array value_to_char5 = union_composition<4, gap, dna4,
dna5>::make_value_to_char();
static_assert(value_to_char5.size() == 10u);
static_assert(value_to_char5[0] == '-');
static_assert(value_to_char5[1] == 'A');
static_assert(value_to_char5[2] == 'C');
static_assert(value_to_char5[3] == 'G');
static_assert(value_to_char5[4] == 'T');
static_assert(value_to_char5[5] == 'A');
static_assert(value_to_char5[6] == 'C');
static_assert(value_to_char5[7] == 'G');
static_assert(value_to_char5[8] == 'T');
static_assert(value_to_char5[9] == 'N');
when preprocessed with -E -std=c++17 with g++ 7.3.1 and compiled with
-std=c++17 trunk gives:
./cc1plus -quiet -std=c++17 pr84684-6.ii
pr84684-6.C: In instantiation of ‘static constexpr auto union_composition<idx,
alphabet_types>::make_value_to_char() [with int idx = 0; alphabet_types =
{dna4}]’:
pr84684-6.C:152:67: required from here
pr84684-6.C:64:43: error: static assertion failed
static_assert (value_to_char_tables[0][2] == check[idx][0][2]);
pr84684-6.C:156:33: error: static assertion failed
static_assert(value_to_char1[2] == 'G');
More information about the Gcc-bugs
mailing list