https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80294

            Bug ID: 80294
           Summary: ICE with constexpr and inheritance
           Product: gcc
           Version: 7.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: maikel.nadolski at googlemail dot com
  Target Milestone: ---

The following code is accepted in clang but causes an ICE in gcc.

Here are more information including links to wandbox:
https://github.com/ericniebler/range-v3/issues/627
https://wandbox.org/permlink/GG89578DXNKbhqgj

--

#include "range/v3/utility/invoke.hpp"
#include "range/v3/utility/compressed_pair.hpp"

namespace foo
{
  template <typename Exception = std::logic_error>
  struct Throws_if_false
  {
    template <typename P, typename ...A>
    constexpr void
    operator()(P pred, A&& ...args) const
    {
      if (!ranges::invoke(pred, std::forward<A>(args)...)) {
        throw Exception("Some Error occured");
      }
    }
  };

  template <auto N, typename Comp = std::less<>>
  class GreaterThan: private ranges::box<Comp, GreaterThan<N, Comp>>
  {
    using base = ranges::box<Comp, GreaterThan<N, Comp>>;
    using base::get;
  public:
    using base::base;

    template <typename T>
      constexpr bool operator()(const T& x) const
      {
        return get()(N, x);
      }
  };

  template <typename T, typename P, typename E = Throws_if_false<>>
  class Constrained: private ranges::compressed_pair<P, E>
  {
  private:
    using base_type = ranges::compressed_pair<P, E>;
    T value_;

    constexpr T enforce_constraint(T value) const
    {
      ranges::invoke(executor(), predicate(), value);
      assert(ranges::invoke(predicate(), value));
      return value;
    }

  public:
    constexpr Constrained(const T& value)
    : Constrained(value, P(), E()) {}

    template <typename T_>
      constexpr Constrained(T_&& value, P predicate, E executor)
      : base_type{std::move(predicate), std::move(executor)}
      , value_{enforce_constraint(std::forward<T_>(value))}
      {}

    constexpr const P& predicate() const& noexcept
    { return base_type::first(); }

    constexpr const E& executor() const& noexcept
    { return base_type::second(); }
  };
}

int main()
{
  using Positive = foo::Constrained<int, foo::GreaterThan<0>>;
  constexpr Positive n [[maybe_unused]] = 1;
}

--

Error message:

prog.cc: In function 'int main()':
prog.cc:69:43:   in constexpr expansion of 'foo::Constrained<int,
foo::GreaterThan<0> >(1)'
prog.cc:50:34:   in constexpr expansion of '((foo::Constrained<int,
foo::GreaterThan<0> >*)this)->foo::Constrained<int, foo::GreaterThan<0>
>::Constrained<const int&>(value, (foo::GreaterThan<0>(),
foo::GreaterThan<0>()), (foo::Throws_if_false<>(), foo::Throws_if_false<>()))'
prog.cc:55:34:   in constexpr expansion of '((foo::Constrained<int,
foo::GreaterThan<0> >*)this)->foo::Constrained<int, foo::GreaterThan<0>
>::enforce_constraint(((int)std::forward<const int&>(value)))'
prog.cc:43:21:   in constexpr expansion of
'ranges::v3::function_objects::invoke.ranges::v3::invoke_fn::operator()<const
foo::Throws_if_false<>&, const foo::GreaterThan<0, std::less<void> >&,
int&>(((const foo::Constrained<int, foo::GreaterThan<0>
>*)this)->foo::Constrained<int, foo::GreaterThan<0> >::executor(), ((const
foo::Constrained<int, foo::GreaterThan<0> >*)this)->foo::Constrained<int,
foo::GreaterThan<0> >::predicate(), value)'
prog.cc:69:43: internal compiler error: Segmentation fault
   constexpr Positive n [[maybe_unused]] = 1;
                                           ^
0xad407f crash_signal
        ../../source/gcc/toplev.c:337
0x6d0099 reduced_constant_expression_p(tree_node*)
        ../../source/gcc/cp/constexpr.c:1709
0x6d00f1 reduced_constant_expression_p(tree_node*)
        ../../source/gcc/cp/constexpr.c:1719
0x6d0184 verify_constant
        ../../source/gcc/cp/constexpr.c:1742
0x6d5443 cxx_eval_indirect_ref
        ../../source/gcc/cp/constexpr.c:3161
0x6d5443 cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4146
0x6d503a cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4067
0x6d3d91 cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4209
0x6d1f7f cxx_bind_parameters_in_call
        ../../source/gcc/cp/constexpr.c:1265
0x6d1f7f cxx_eval_call_expression
        ../../source/gcc/cp/constexpr.c:1535
0x6d33fd cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4007
0x6d303a cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4124
0x6d303a cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4124
0x6d39e8 cxx_eval_statement_list
        ../../source/gcc/cp/constexpr.c:3740
0x6d39e8 cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4468
0x6d28f6 cxx_eval_call_expression
        ../../source/gcc/cp/constexpr.c:1642
0x6d33fd cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4007
0x6d303a cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4124
0x6d303a cxx_eval_constant_expression
        ../../source/gcc/cp/constexpr.c:4124
0x6d39e8 cxx_eval_statement_list
        ../../source/gcc/cp/constexpr.c:3740
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

Reply via email to