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

            Bug ID: 78846
           Summary: std1y compiler infinite output
           Product: gcc
           Version: 6.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: k...@st-andrews.ac.uk
  Target Milestone: ---

Created attachment 40358
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40358&action=edit
.ii file

I created a c++14 program to implement lazy evaluation, but the compiler seems
to be producing infinite output.

Machine (1)
System: Darwin 13.4.0 x86_64 i386
G++: g++-6 (Homebrew gcc 6.2.0) 6.2.0
Command: g++-6 -std=c++1y binary_operation.cpp

Machine (2)
System: Linux 4.4.0-53-generic x86_64 x86_64 x86_64 GNU/Linux
G++: g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Command: g++ -std=c++1y binary_operation.cpp

(Actually, trying to compile with clang produces the same result).

For preprocessed file, see the attachment.

CODE
--------------------------------------------------

#include <iostream>

static const auto add = [](auto a, auto b) {return a + b;};
static const auto sub = [](auto a, auto b) {return a - b;};
static const auto mul = [](auto a, auto b) {return a * b;};
static const auto frac = [](auto a, auto b) {return a / b;};

template <class A, class B, class F> class BinaryOP;

template <class A, class B> using Addition = BinaryOP <A, B, decltype(add)>;
template <class A, class B> using Subtraction = BinaryOP <A, B, decltype(sub)>;
template <class A, class B> using Multiplication = BinaryOP <A, B,
decltype(mul)>;
template <class A, class B> using Division = BinaryOP <A, B, decltype(frac)>;

static const auto make_binop = [](auto a, auto b, auto F) { return
BinaryOP<decltype(a), decltype(b), decltype(F)>(a, b, F); };
static const auto make_add = [](auto a, auto b) { return make_binop(a, b, add);
};
static const auto make_sub = [](auto a, auto b) { return
Subtraction<decltype(a), decltype(b)>(a, b, sub); };
static const auto make_mul = [](auto a, auto b) { return
Multiplication<decltype(a), decltype(b)>(a, b, mul); };
static const auto make_div = [](auto a, auto b) { return Division<decltype(a),
decltype(b)>(a, b, frac); };

template <class A, class B, class F>
class BinaryOP {
protected:
  typedef BinaryOP <A, B, F> THIS_T;
  A lhs;
  B rhs;
  F func;
public:
  BinaryOP(A lhs, B rhs, F &func):
    lhs(lhs), rhs(rhs), func(func)
  {}
  virtual ~BinaryOP()
  {}
  template <class T>
  operator T() {
    return func(T(lhs), T(rhs));
  }
  template <class T>
  Addition<THIS_T, T> operator+(const T &other) {
    return make_add(*this, other);
  }
  template <class T>
  Subtraction<THIS_T, T> operator-(const T &other) {
    return make_sub(*this, other);
  }
  template <class T>
  Multiplication<THIS_T, T> operator*(const T &other) {
    return make_mul(*this, other);
  }
  template <class T>
  Division<THIS_T, T> operator/(const T &other) {
    return make_div(*this, other);
  }

  friend std::ostream &operator<<(std::ostream &os, const THIS_T &bin) {
    os << "(binop: " << bin.lhs << ", " << bin.rhs << ")";
    return os;
  }
};

int main() {
  std::cout << make_add(2, 3) + make_sub(5, 6) * make_add(3, 0) << std::endl;
}

--------------------------------------------------

The problem appeared when I changed:

static const auto make_add = [](auto a, auto b) { return Addition<decltype(A),
decltype(B), decltype(add)>(a, b, add); };

into

static const auto make_add = [](auto a, auto b) { return make_binop(a, b, add);
};


OUTPUT (first few lines):
--------------------------------------------------

binary_operator.cpp: In instantiation of 'BinaryOP<A, B, F>::operator T() [with
T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >; A = int; B = int; F = <lambda(auto:1,
auto:2)>]':
binary_operator.cpp:47:17:   required from 'BinaryOP<A, B, F>::operator T()
[with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, <lambda(auto:1,
auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >,
BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >;
F = <lambda(auto:1, auto:2)>]'
binary_operator.cpp:51:33:   required from 'Addition<BinaryOP<A, B, F>, T>
BinaryOP<A, B, F>::operator+(const T&) [with T = BinaryOP<BinaryOP<int, int,
const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
const<lambda(auto:5, auto:6)> >; A = int; B = int; F = <lambda(auto:1,
auto:2)>; Addition<BinaryOP<A, B, F>, T> = BinaryOP<BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3,
auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5,
auto:6)> >, const<lambda(auto:1, auto:2)> >]'
binary_operator.cpp:73:63:   required from here
binary_operator.cpp:47:17: error: no matching function for call to
'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int,
int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1,
auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)>
>::BinaryOP(int&)'
     return func(T(lhs), T(rhs));
                 ^~~~~~
binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F)
[with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B =
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F =
const<lambda(auto:1, auto:2)>]
   BinaryOP(A lhs, B rhs, F func):
   ^~~~~~~~
binary_operator.cpp:35:3: note:   candidate expects 3 arguments, 1 provided
binary_operator.cpp:22:7: note: candidate: constexpr BinaryOP<BinaryOP<int,
int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int,
const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)>
>::BinaryOP(const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >&)
 class BinaryOP {
       ^~~~~~~~
binary_operator.cpp:22:7: note:   no known conversion for argument 1 from 'int'
to 'const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >&'
binary_operator.cpp:47:25: error: no matching function for call to
'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int,
int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1,
auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)>
>::BinaryOP(int&)'
     return func(T(lhs), T(rhs));
                         ^~~~~~
binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F)
[with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B =
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F =
const<lambda(auto:1, auto:2)>]
   BinaryOP(A lhs, B rhs, F func):
   ^~~~~~~~
binary_operator.cpp:35:3: note:   candidate expects 3 arguments, 1 provided
binary_operator.cpp:22:7: note: candidate: constexpr BinaryOP<BinaryOP<int,
int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int,
const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)>
>::BinaryOP(const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >&)
 class BinaryOP {
       ^~~~~~~~
binary_operator.cpp:22:7: note:   no known conversion for argument 1 from 'int'
to 'const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >&'
binary_operator.cpp: In instantiation of 'BinaryOP<A, B, F>::operator T() [with
T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >; A = int; B = int; F = const<lambda(auto:3,
auto:4)>]':
binary_operator.cpp:47:17:   required from 'BinaryOP<A, B, F>::operator T()
[with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, const<lambda(auto:3,
auto:4)> >; B = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; F =
const<lambda(auto:5, auto:6)>]'
binary_operator.cpp:47:25:   required from 'BinaryOP<A, B, F>::operator T()
[with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >,
const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, <lambda(auto:1,
auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >,
BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >;
F = <lambda(auto:1, auto:2)>]'
binary_operator.cpp:51:33:   required from 'Addition<BinaryOP<A, B, F>, T>
BinaryOP<A, B, F>::operator+(const T&) [with T = BinaryOP<BinaryOP<int, int,
const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >,
const<lambda(auto:5, auto:6)> >; A = int; B = int; F = <lambda(auto:1,
auto:2)>; Addition<BinaryOP<A, B, F>, T> = BinaryOP<BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3,
auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5,
auto:6)> >, const<lambda(auto:1, auto:2)> >]'
binary_operator.cpp:73:63:   required from here
binary_operator.cpp:47:17: error: no matching function for call to
'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int,
int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1,
auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)>
>::BinaryOP(int&)'
     return func(T(lhs), T(rhs));
                 ^~~~~~
binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F)
[with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B =
BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int,
<lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F =
const<lambda(auto:1, auto:2)>]
   BinaryOP(A lhs, B rhs, F func):
   ^~~~~~~~

...

--------------------------------------------------

Reply via email to