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: [email protected]
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):
^~~~~~~~
...
--------------------------------------------------