coord: mitigate gcc ICE when using redim

This commit is contained in:
Danny Robson 2018-01-17 13:27:57 +11:00
parent b4e242ffd4
commit a8b4c93ccd
2 changed files with 33 additions and 18 deletions

View File

@ -148,21 +148,24 @@ namespace util::coord {
/// ///
/// explicitly does not allow a fill parameter given it can't be used /// explicitly does not allow a fill parameter given it can't be used
/// when reducing dimensions. /// when reducing dimensions.
///
/// HACK,gcc#,gcc-7.x: This function _must not_ use std::copy or
/// similar algorithms to move the data as it produces an ICE on some
/// code fragements if it does. Namely:
/// "internal compiler error: in trunc_int_for_mode, at explow.c:55"
template < template <
size_t D, size_t D,
typename _sfinae = SelfT typename = std::enable_if_t<
> has_redim_v<SelfT> && S >= D,
std::enable_if_t< void
has_redim_v<_sfinae>, >
redim_t<_sfinae,D>
> >
auto
redim (void) const redim (void) const
{ {
redim_t<SelfT,D> out; redim_t<SelfT,D> out;
for (size_t i = 0; i < D; ++i)
std::copy_n (std::cbegin (this->data), out[i] = this->data[i];
min (S, D),
std::begin (out.data));
return out; return out;
} }
@ -174,17 +177,24 @@ namespace util::coord {
/// ///
/// explicitly requires a fill parameter so that we avoid undefined /// explicitly requires a fill parameter so that we avoid undefined
/// values. /// values.
///
/// HACK,gcc#,gcc-7.x: This function _must not_ use std::copy or
/// similar algorithms to move the data as it produces an ICE on some
/// code fragements if it does. Namely:
/// "internal compiler error: in trunc_int_for_mode, at explow.c:55"
template<size_t D,typename _sfinae = SelfT> template<size_t D,typename _sfinae = SelfT>
std::enable_if_t< std::enable_if_t<
has_redim_v<_sfinae>, has_redim_v<_sfinae> && S <= D,
redim_t<_sfinae,D> redim_t<_sfinae,D>
> >
redim (const redim_t<_sfinae,D> fill) const redim (const redim_t<_sfinae,D> fill) const
{ {
redim_t<SelfT,D> out; redim_t<SelfT,D> out;
auto next = std::copy (cbegin (), cend (), std::begin (out)); for (size_t i = 0; i < S; ++i)
std::copy (std::cbegin (fill) + S, std::cend (fill), next); out[i] = this->data[i];
for (size_t i = S; i < D; ++i)
out[i] = fill[i];
return out; return out;
} }
@ -194,20 +204,26 @@ namespace util::coord {
/// ///
/// explicitly requires a fill parameter so that we avoid undefined /// explicitly requires a fill parameter so that we avoid undefined
/// values. /// values.
///
/// HACK,gcc#,gcc-7.x: This function _must not_ use std::copy or
/// similar algorithms to move the data as it produces an ICE on some
/// code fragements if it does. Namely:
/// "internal compiler error: in trunc_int_for_mode, at explow.c:55"
template < template <
size_t D, size_t D,
typename _sfinae = SelfT typename _sfinae = SelfT
> >
std::enable_if_t< std::enable_if_t<
has_redim_v<_sfinae>, has_redim_v<_sfinae> && S <= D,
redim_t<_sfinae,D> redim_t<_sfinae,D>
> >
redim (T fill) const redim (T fill) const
{ {
redim_t<SelfT,D> out; redim_t<SelfT,D> out;
for (size_t i = 0; i < S; ++i)
auto next = std::copy (cbegin (), cend (), std::begin (out)); out[i] = this->data[i];
std::fill (next, std::end (out), fill); for (size_t i = S; i < D; ++i)
out[i] = fill;
return out; return out;
} }

View File

@ -20,6 +20,7 @@ main (void)
const point2f r { 0.f, 1.f }; const point2f r { 0.f, 1.f };
tap.expect_eq (q, r, "redim to lower dimension"); tap.expect_eq (q, r, "redim to lower dimension");
} }
// Redim to higher dimension without fill // Redim to higher dimension without fill
@ -39,7 +40,6 @@ main (void)
// //
// HACK: This fails under GCC-7.1.0, and i'm not wasting any more time // HACK: This fails under GCC-7.1.0, and i'm not wasting any more time
// reducing this test case. it's _really_ template heavy. // reducing this test case. it's _really_ template heavy.
#if !(__GNUC_PREREQ (7, 1))
{ {
static const point4f FILL (1.f, 2.f, 3.f, 4.f); static const point4f FILL (1.f, 2.f, 3.f, 4.f);
const point2f p (0.1f, 1.f); const point2f p (0.1f, 1.f);
@ -54,7 +54,6 @@ main (void)
"redim to higher with fill" "redim to higher with fill"
); );
} }
#endif
// Simple linking check for coord type casting. Relies on truncation. // Simple linking check for coord type casting. Relies on truncation.
{ {