This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] libstdc++/69222 Prevent recursive instantiation in std::function
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Tue, 12 Jan 2016 14:56:35 +0000
- Subject: [patch] libstdc++/69222 Prevent recursive instantiation in std::function
- Authentication-results: sourceware.org; auth=none
This fixes PR 69222 and PR 69005 for gcc-5-branch, by ensuring we
don't try to determine the result of invoking the function(Functor)
constructor argument when the type is incomplete (because that might
require instantiating the constructor again, which recurses).
Jason fixed 69005 on trunk by making the front end skip that
constructor when performing overload resolution for copy construction,
because it cannot be instantiated to make a copy, but there is still a
problem on the branch, so I'm fixing it in the library. I'm making the
same change on trunk, because it's an improvement anyway.
Tested x86_64-linux, committed to trunk and gcc-5-branch.
commit 540303f8e8f24a89ecd3698c70efe9ab753ef9d9
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Tue Jan 12 14:55:00 2016 +0000
Prevent recursive instantiation in std::function
PR libstdc++/69005
PR libstdc++/69222
* include/std/functional (function::_Invoke): Remove, use result_of.
(function::_Callable): Replace alias template with class template
and use partial specialization instead of _NotSelf alias template.
(function(_Functor)): Add "not self" constraint so that _Callable is
not used while type is incomplete.
* testsuite/20_util/function/69222.cc: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@232274 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 139be61..717d1bf 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1977,19 +1977,14 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
{
typedef _Res _Signature_type(_ArgTypes...);
- template<typename _Functor>
- using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
- (std::declval<_ArgTypes>()...) );
+ template<typename _Func,
+ typename _Res2 = typename result_of<_Func(_ArgTypes...)>::type>
+ struct _Callable : __check_func_return_type<_Res2, _Res> { };
// Used so the return type convertibility checks aren't done when
// performing overload resolution for copy construction/assignment.
template<typename _Tp>
- using _NotSelf = __not_<is_same<_Tp, function>>;
-
- template<typename _Functor>
- using _Callable
- = __and_<_NotSelf<_Functor>,
- __check_func_return_type<_Invoke<_Functor>, _Res>>;
+ struct _Callable<function, _Tp> : false_type { };
template<typename _Cond, typename _Tp>
using _Requires = typename enable_if<_Cond::value, _Tp>::type;
@@ -2054,6 +2049,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
* reference_wrapper<F>, this function will not throw.
*/
template<typename _Functor,
+ typename = _Requires<__not_<is_same<_Functor, function>>, void>,
typename = _Requires<_Callable<_Functor>, void>>
function(_Functor);
@@ -2246,7 +2242,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
}
template<typename _Res, typename... _ArgTypes>
- template<typename _Functor, typename>
+ template<typename _Functor, typename, typename>
function<_Res(_ArgTypes...)>::
function(_Functor __f)
: _Function_base()
diff --git a/libstdc++-v3/testsuite/20_util/function/69222.cc b/libstdc++-v3/testsuite/20_util/function/69222.cc
new file mode 100644
index 0000000..7c9dfec
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function/69222.cc
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <functional>
+
+// Reduced from c++/69005
+struct Foo {
+ std::function<void(Foo)> f;
+};
+
+extern Foo exfoo;
+Foo f(exfoo);
+Foo& r = f = exfoo;