Tested on Linux-PPC64. The problem is a tad tricky, since
the bug triggered by the testcase is in a constructor that
will not be used, but will cause endless meta-recursion
via checking convertibility of an incomplete type that will
cause further recursion. While there might be ways to fix
that in the traits themselves, this is a straightforward fix,
for certain tuple-specific values of "straightforward". ;)
And hey, the problem and its solution were, once the bug
report came in, obvious to the resident tuple-hacker between
my chair and my keyboard. :)
2015-10-05 Ville Voutilainen <[email protected]>
PR 67844.
* include/std/tuple (_TC::_NonNestedTuple): Eagerly reject
conversions from tuple types same as the target tuple.
* testsuite/20_util/tuple/67844.cc: New.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 751d7eb..8af01f4 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -457,6 +457,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+ template<typename... _Elements>
+ class tuple;
// Concept utility functions, reused in conditionally-explicit
// constructors.
@@ -490,7 +492,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _SrcTuple>
static constexpr bool _NonNestedTuple()
{
- return __and_<__not_<is_convertible<_SrcTuple, _Elements...>>,
+ return __and_<__not_<is_same<tuple<_Elements...>,
+ typename remove_cv<
+ typename remove_reference<_SrcTuple>::type
+ >::type>>,
+ __not_<is_convertible<_SrcTuple, _Elements...>>,
__not_<is_constructible<_Elements..., _SrcTuple>>
>::value;
}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/67844.cc
b/libstdc++-v3/testsuite/20_util/tuple/67844.cc
new file mode 100644
index 0000000..5635462
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/67844.cc
@@ -0,0 +1,24 @@
+// { dg-do compile }
+
+#include <tuple>
+
+struct A
+{
+ template <typename T>
+ A(T)
+ {
+ }
+
+ A(const A&) = default;
+ A(A&&) = default;
+ A& operator=(const A&) = default;
+ A& operator=(A&&) = default;
+ ~A() = default;
+};
+
+int main()
+{
+ auto x = A{7};
+ std::make_tuple(x);
+}
+