[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