diff mbox

[v3] fix libstdc++/48521

Message ID BANLkTik_aeH_zPT5LGOgCHMhKePFf8tLnw@mail.gmail.com
State New
Headers show

Commit Message

Jonathan Wakely April 19, 2011, 1:26 p.m. UTC
2011-04-19  Jonathan Wakely  <jwakely.gcc@gmail.com>

        PR libstdc++/48521
        * include/std/type_traits (result_of): Handle pointer to member.
        * include/std/functional (__invoke): Likewise.
        (_Function_to_function_pointer): Remove.
        (_Reference_wrapper_base): Provide nested types independent of
        unary_function and binary_function.
        (reference_wrapper::operator()): DR 2017.
        (ref(const A&&), cref(const A&&): Define as deleted.
        * include/std/future (async): Simplify SFINAE and use result_of to
        support pointer to member.
        * testsuite/20_util/reference_wrapper/invoke.cc: Test pointer to
        member.
        * testsuite/20_util/reference_wrapper/24803.cc: Likewise.
        * testsuite/20_util/reference_wrapper/typedefs.cc: Test for types
        instead of derivation from unary_function and binary_function.
        * testsuite/20_util/declval/requirements/1_neg.cc: Adjust.
        * testsuite/20_util/reference_wrapper/invoke-2.cc: New.
        * testsuite/20_util/reference_wrapper/ref_neg.c: New.
        * testsuite/20_util/reference_wrapper/typedefs-3.c: New.

This resolves a few issues in <functional> which I first noticed
because our std::async didn't work with pointers to member. To fix
that I needed to make result_of support pointer to member, then use
result_of in async, which required changing the enable_if otherwise we
form an invalid result_of expression outside the immediate context of
the type deduction, where SFINAE doesn't apply.

I implemented DR 2017 (reference wrapper makes incorrect use of
result_of) and because we now use a reference to the wrapped type in
the result_of expression we don't need Function_to_function_pointer to
prevent forming an invalid expression.

I made reference_wrapper define the nested
{first_,second_,}argument_type typedefs correctly if the wrapped type
defines them. Previously we only did so if the nested type derived
from {unary,binary}_function but the C++0x draft was changed to stop
depending on those types.

Finally, I've also added missing ref/cref overloads to prevent
creating reference_wrapper to rvalues.

mem_fn doesn't yet support varargs member functions, I'll fix that
when PR c++/48424 is fixed.

Tested x86_64-linux, committed to trunk.  Will wait a day or two and
commit to 4.6 too.
diff mbox

Patch

Index: include/std/type_traits
===================================================================
--- include/std/type_traits	(revision 172708)
+++ include/std/type_traits	(working copy)
@@ -1583,18 +1583,6 @@ 
 
   /// underlying_type (still unimplemented)
 
-  /// result_of
-  template<typename _Signature>
-    class result_of;
-
-  template<typename _Functor, typename... _ArgTypes>
-    struct result_of<_Functor(_ArgTypes...)>
-    {
-      typedef
-        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
-        type;
-    };
-
   /// declval
   template<typename _Tp>
     struct __declval_protector
@@ -1612,6 +1600,98 @@ 
       return __declval_protector<_Tp>::__delegate();
     }
 
+  /// result_of
+  template<typename _Signature>
+    class result_of;
+
+  template<typename _MemPtr, typename _Arg>
+    struct _Result_of_memobj;
+
+  template<typename _Res, typename _Class, typename _Arg>
+    struct _Result_of_memobj<_Res _Class::*, _Arg>
+    {
+    private:
+      typedef _Res _Class::* _Func;
+
+      template<typename _Tp>
+	static _Tp _S_get(const _Class&);
+      template<typename _Tp>
+	static decltype(*std::declval<_Tp>()) _S_get(...);
+        
+    public:
+      typedef
+        decltype(_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
+        __type;
+    };
+
+  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
+    struct _Result_of_memfun;
+
+  template<typename _Res, typename _Class, typename _Arg, typename... _Args>
+    struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...>
+    {
+    private:
+      typedef _Res _Class::* _Func;
+
+      template<typename _Tp>
+	static _Tp _S_get(const _Class&);
+      template<typename _Tp>
+	static decltype(*std::declval<_Tp>()) _S_get(...);
+        
+    public:
+      typedef
+        decltype((_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
+            (std::declval<_Args>()...) )
+        __type;
+    };
+
+  template<bool, bool, typename _Functor, typename... _ArgTypes>
+    struct _Result_of_impl;
+
+  template<typename _Functor, typename... _ArgTypes>
+    struct _Result_of_impl<false, false, _Functor, _ArgTypes...>
+    {
+      typedef
+        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
+        __type;
+    };
+
+  template<typename _MemPtr, typename _Arg>
+    struct _Result_of_impl<true, false, _MemPtr, _Arg>
+    : _Result_of_memobj<typename remove_reference<_MemPtr>::type, _Arg>
+    {
+      typedef typename _Result_of_memobj<
+	typename remove_reference<_MemPtr>::type, _Arg>::__type
+	__type;
+    };
+
+  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
+    struct _Result_of_impl<false, true, _MemPtr, _Arg, _ArgTypes...>
+    : _Result_of_memfun<typename remove_reference<_MemPtr>::type, _Arg,
+                        _ArgTypes...>
+    {
+      typedef typename _Result_of_memfun<
+	typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type
+	__type;
+    };
+
+  template<typename _Functor, typename... _ArgTypes>
+    struct result_of<_Functor(_ArgTypes...)>
+    : _Result_of_impl<is_member_object_pointer<
+                        typename remove_reference<_Functor>::type >::value,
+                      is_member_function_pointer<
+			typename remove_reference<_Functor>::type >::value,
+		      _Functor, _ArgTypes...>
+    {
+      typedef typename _Result_of_impl<
+	is_member_object_pointer<
+	  typename remove_reference<_Functor>::type >::value,
+        is_member_function_pointer<
+	  typename remove_reference<_Functor>::type >::value,
+       	_Functor, _ArgTypes...>::__type
+	type;
+    };
+
   /**
    *  Use SFINAE to determine if the type _Tp has a publicly-accessible
    *  member type _NTYPE.
Index: include/std/functional
===================================================================
--- include/std/functional	(revision 172708)
+++ include/std/functional	(working copy)
@@ -212,19 +212,6 @@ 
       static const bool value = sizeof(__test((_Tp*)0)) == 1;
     };
 
-  /// Turns a function type into a function pointer type
-  template<typename _Tp, bool _IsFunctionType = is_function<_Tp>::value>
-    struct _Function_to_function_pointer
-    {
-      typedef _Tp type;
-    };
-
-  template<typename _Tp>
-    struct _Function_to_function_pointer<_Tp, true>
-    {
-      typedef _Tp* type;
-    };
-
   /**
    * Invoke a function object, which may be either a member pointer or a
    * function object. The first parameter will tell which.
@@ -235,20 +222,33 @@ 
 	     (!is_member_pointer<_Functor>::value
 	      && !is_function<_Functor>::value
 	      && !is_function<typename remove_pointer<_Functor>::type>::value),
-	     typename result_of<_Functor(_Args...)>::type
+	     typename result_of<_Functor(_Args&&...)>::type
 	   >::type
     __invoke(_Functor& __f, _Args&&... __args)
     {
       return __f(std::forward<_Args>(__args)...);
     }
 
+  template<typename _Functor, typename... _Args>
+    inline
+    typename enable_if<
+             (is_member_pointer<_Functor>::value
+              && !is_function<_Functor>::value
+              && !is_function<typename remove_pointer<_Functor>::type>::value),
+             typename result_of<_Functor(_Args&&...)>::type
+           >::type
+    __invoke(_Functor& __f, _Args&&... __args)
+    {
+      return mem_fn(__f)(std::forward<_Args>(__args)...);
+    }
+
   // To pick up function references (that will become function pointers)
   template<typename _Functor, typename... _Args>
     inline
     typename enable_if<
 	     (is_pointer<_Functor>::value
 	      && is_function<typename remove_pointer<_Functor>::type>::value),
-	     typename result_of<_Functor(_Args...)>::type
+	     typename result_of<_Functor(_Args&&...)>::type
 	   >::type
     __invoke(_Functor __f, _Args&&... __args)
     {
@@ -263,40 +263,43 @@ 
   template<bool _Unary, bool _Binary, typename _Tp>
     struct _Reference_wrapper_base_impl;
 
-  // Not a unary_function or binary_function, so try a weak result type.
+  // None of the nested argument types.
   template<typename _Tp>
     struct _Reference_wrapper_base_impl<false, false, _Tp>
     : _Weak_result_type<_Tp>
     { };
 
-  // unary_function but not binary_function
+  // Nested argument_type only.
   template<typename _Tp>
     struct _Reference_wrapper_base_impl<true, false, _Tp>
-    : unary_function<typename _Tp::argument_type,
-		     typename _Tp::result_type>
-    { };
+    : _Weak_result_type<_Tp>
+    {
+      typedef typename _Tp::argument_type argument_type;
+    };
 
-  // binary_function but not unary_function
+  // Nested first_argument_type and second_argument_type only.
   template<typename _Tp>
     struct _Reference_wrapper_base_impl<false, true, _Tp>
-    : binary_function<typename _Tp::first_argument_type,
-		      typename _Tp::second_argument_type,
-		      typename _Tp::result_type>
-    { };
+    : _Weak_result_type<_Tp>
+    {
+      typedef typename _Tp::first_argument_type first_argument_type;
+      typedef typename _Tp::second_argument_type second_argument_type;
+    };
 
-  // Both unary_function and binary_function. Import result_type to
-  // avoid conflicts.
+  // All the nested argument types.
    template<typename _Tp>
     struct _Reference_wrapper_base_impl<true, true, _Tp>
-    : unary_function<typename _Tp::argument_type,
-		     typename _Tp::result_type>,
-      binary_function<typename _Tp::first_argument_type,
-		      typename _Tp::second_argument_type,
-		      typename _Tp::result_type>
+    : _Weak_result_type<_Tp>
     {
-      typedef typename _Tp::result_type result_type;
+      typedef typename _Tp::argument_type argument_type;
+      typedef typename _Tp::first_argument_type first_argument_type;
+      typedef typename _Tp::second_argument_type second_argument_type;
     };
 
+  _GLIBCXX_HAS_NESTED_TYPE(argument_type)
+  _GLIBCXX_HAS_NESTED_TYPE(first_argument_type)
+  _GLIBCXX_HAS_NESTED_TYPE(second_argument_type)
+
   /**
    *  Derives from unary_function or binary_function when it
    *  can. Specializations handle all of the easy cases. The primary
@@ -306,8 +309,9 @@ 
   template<typename _Tp>
     struct _Reference_wrapper_base
     : _Reference_wrapper_base_impl<
-      _Derives_from_unary_function<_Tp>::value,
-      _Derives_from_binary_function<_Tp>::value,
+      __has_argument_type<_Tp>::value,
+      __has_first_argument_type<_Tp>::value
+      && __has_second_argument_type<_Tp>::value,
       _Tp>
     { };
 
@@ -422,12 +426,8 @@ 
     class reference_wrapper
     : public _Reference_wrapper_base<typename remove_cv<_Tp>::type>
     {
-      // If _Tp is a function type, we can't form result_of<_Tp(...)>,
-      // so turn it into a function pointer type.
-      typedef typename _Function_to_function_pointer<_Tp>::type
-	_M_func_type;
+      _Tp* _M_data;
 
-      _Tp* _M_data;
     public:
       typedef _Tp type;
 
@@ -456,7 +456,7 @@ 
       { return *_M_data; }
 
       template<typename... _Args>
-	typename result_of<_M_func_type(_Args...)>::type
+	typename result_of<_Tp&(_Args&&...)>::type
 	operator()(_Args&&... __args) const
 	{
 	  return __invoke(get(), std::forward<_Args>(__args)...);
@@ -476,6 +476,12 @@ 
     cref(const _Tp& __t)
     { return reference_wrapper<const _Tp>(__t); }
 
+  template<typename _Tp>
+    void ref(const _Tp&&) = delete;
+
+  template<typename _Tp>
+    void cref(const _Tp&&) = delete;
+
   /// Partial specialization.
   template<typename _Tp>
     inline reference_wrapper<_Tp>
Index: include/std/future
===================================================================
--- include/std/future	(revision 172708)
+++ include/std/future	(working copy)
@@ -142,11 +142,19 @@ 
     future<typename result_of<_Fn(_Args...)>::type>
     async(launch __policy, _Fn&& __fn, _Args&&... __args);
 
+  template<typename _FnCheck, typename _Fn, typename... _Args>
+    struct __async_sfinae_helper
+    {
+      typedef future<typename result_of<_Fn(_Args...)>::type> type;
+    };
+
   template<typename _Fn, typename... _Args>
+    struct __async_sfinae_helper<launch, _Fn, _Args...>
+    { };
+
+  template<typename _Fn, typename... _Args>
     typename
-    enable_if<!is_same<typename decay<_Fn>::type, launch>::value,
-              future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))>
-             >::type
+    __async_sfinae_helper<typename decay<_Fn>::type, _Fn, _Args...>::type
     async(_Fn&& __fn, _Args&&... __args);
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
@@ -1373,9 +1381,7 @@ 
   /// async, potential overload
   template<typename _Fn, typename... _Args>
     inline typename
-    enable_if<!is_same<typename decay<_Fn>::type, launch>::value,
-              future<decltype(std::declval<_Fn>()(std::declval<_Args>()...))>
-             >::type
+    __async_sfinae_helper<typename decay<_Fn>::type, _Fn, _Args...>::type
     async(_Fn&& __fn, _Args&&... __args)
     {
       return async(launch::any, std::forward<_Fn>(__fn),
Index: testsuite/20_util/reference_wrapper/invoke.cc
===================================================================
--- testsuite/20_util/reference_wrapper/invoke.cc	(revision 172708)
+++ testsuite/20_util/reference_wrapper/invoke.cc	(working copy)
@@ -1,6 +1,6 @@ 
 // { dg-options "-std=gnu++0x" }
 
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 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
@@ -36,6 +36,7 @@ 
   int foo_c(float x)  const          { return truncate_float(x); }
   int foo_v(float x)  volatile       { return truncate_float(x); }
   int foo_cv(float x) const volatile { return truncate_float(x); }
+  int foo_varargs(float x, ...)      { return truncate_float(x); }
 
   int operator()(float x)
   {
@@ -69,6 +70,13 @@ 
 
   ::get_seventeen get_sev;
   ::X x;
+  ::X* xp = &x;
+  int (::X::* p_foo)(float) = &::X::foo;
+  int (::X::* p_foo_c)(float) const = &::X::foo_c;
+  int (::X::* p_foo_v)(float) volatile = &::X::foo_v;
+  int (::X::* p_foo_cv)(float) const volatile = &::X::foo_cv;
+  int (::X::* p_foo_varargs)(float, ...) = &::X::foo_varargs;
+  int ::X::* p_bar = &::X::bar;
 
   const float pi = 3.14;
 
@@ -77,9 +85,27 @@ 
   VERIFY(ref(seventeen)() == 17);
 
   // Function pointers
-  VERIFY(cref(&truncate_float)(pi) == 3);
-  VERIFY(cref(&seventeen)() == 17);
+  VERIFY(cref(truncate_float)(pi) == 3);
+  VERIFY(cref(seventeen)() == 17);
 
+  // Member function pointers
+  VERIFY(ref(p_foo)(x, pi) == 3);
+  VERIFY(ref(p_foo)(xp, pi) == 3);
+  VERIFY(ref(p_foo_c)(x, pi) == 3);
+  VERIFY(ref(p_foo_c)(xp, pi) == 3);
+  VERIFY(ref(p_foo_v)(x, pi) == 3);
+  VERIFY(ref(p_foo_v)(xp, pi) == 3);
+  VERIFY(ref(p_foo_cv)(x, pi) == 3);
+  VERIFY(ref(p_foo_cv)(xp, pi) == 3);
+  // VERIFY(ref(p_foo_varargs)(x, pi) == 3);
+  // VERIFY(ref(p_foo_varargs)(xp, pi, 1, 1) == 3);
+  // VERIFY(ref(p_foo_varargs)(x, pi, 1, 1) == 3);
+  // VERIFY(ref(p_foo_varargs)(xp, pi) == 3);
+
+  // Member data pointers
+  VERIFY(ref(p_bar)(x) == 17);
+  VERIFY(ref(p_bar)(xp) == 17);
+
   // Function objects
   VERIFY(ref(get_sev)() == 17);
   VERIFY(cref(get_sev)() == 17);
Index: testsuite/20_util/reference_wrapper/24803.cc
===================================================================
--- testsuite/20_util/reference_wrapper/24803.cc	(revision 172708)
+++ testsuite/20_util/reference_wrapper/24803.cc	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-options "-std=gnu++0x" }
 // { dg-do compile }
 
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 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
@@ -46,12 +46,18 @@ 
 
 void test01()
 {
+  test_type* null_tt = 0;
+  const test_type* null_ttc = 0;
   int zero;
 
   std::reference_wrapper<double (int)>* pr1(0);
   verify_return_type((*pr1)(0), double());
   std::reference_wrapper<double (*)(int)>* pr2(0);
   verify_return_type((*pr2)(0), double());
+  std::reference_wrapper<int (test_type::*)()>* pr3(0);
+  verify_return_type((*pr3)(null_tt), int());
+  std::reference_wrapper<int (test_type::*)()const>* pr4(0);
+  verify_return_type((*pr4)(null_ttc), int());
   std::reference_wrapper<functor1>* pr5(0);
 
   // libstdc++/24803
@@ -62,6 +68,10 @@ 
   verify_return_type((*pr1b)(0, 0), double());
   std::reference_wrapper<double (*)(int, char)>* pr2b(0);
   verify_return_type((*pr2b)(0, 0), double());
+  std::reference_wrapper<int (test_type::*)(char)>* pr3b(0);
+  verify_return_type((*pr3b)(null_tt,zero), int());
+  std::reference_wrapper<int (test_type::*)()const>* pr4b(0);
+  verify_return_type((*pr4b)(null_ttc), int());
   std::reference_wrapper<functor2>* pr5b(0);
 
   // libstdc++/24803
Index: testsuite/20_util/reference_wrapper/typedefs.cc
===================================================================
--- testsuite/20_util/reference_wrapper/typedefs.cc	(revision 172708)
+++ testsuite/20_util/reference_wrapper/typedefs.cc	(working copy)
@@ -1,6 +1,7 @@ 
+// { dg-do compile }
 // { dg-options "-std=gnu++0x" }
 
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 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
@@ -19,11 +20,7 @@ 
 
 #include <functional>
 #include <type_traits>
-#include <testsuite_hooks.h>
-#include <testsuite_tr1.h>
 
-using namespace __gnu_test;
-
 struct X {};
 
 struct int_result_type { typedef int result_type; };
@@ -41,43 +38,18 @@ 
 
 void test01()
 {
-  bool test __attribute__((unused)) = true;
-
   using std::reference_wrapper;
   using std::is_same;
-  using std::is_convertible;
-  using std::unary_function;
-  using std::binary_function;
 
   // Check result_type typedef
-  VERIFY((is_same<reference_wrapper<int_result_type>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<derives_unary>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<derives_binary>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<derives_unary_binary>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<int(void)>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<int(*)(void)>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<int (::X::*)()>::result_type, int>::value));
-  VERIFY((is_same<reference_wrapper<int (::X::*)(float)>::result_type, int>::value));
-
-  // Check derivation from unary_function
-  VERIFY((is_convertible<reference_wrapper<derives_unary>*, unary_function<int, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<derives_unary_binary>*, unary_function<int, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int(int)>*, unary_function<int, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int(*)(int)>*, unary_function<int, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)()>*, unary_function< ::X*, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)() const>*, unary_function<const ::X*, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)() volatile>*, unary_function<volatile ::X*, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)() const volatile>*, unary_function<const volatile ::X*, int>*>::value));
-
-  // Check derivation from binary_function
-  VERIFY((is_convertible<reference_wrapper<derives_binary>*, binary_function<int, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<derives_unary_binary>*, binary_function<int, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int(int, float)>*, binary_function<int, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int(*)(int, float)>*, binary_function<int, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)(float)>*, binary_function< ::X*, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)(float) const>*, binary_function<const ::X*, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)(float) volatile>*, binary_function<volatile ::X*, float, int>*>::value));
-  VERIFY((is_convertible<reference_wrapper<int (::X::*)(float) const volatile>*, binary_function<const volatile ::X*, float, int>*>::value));
+  static_assert( is_same<reference_wrapper<int_result_type>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<derives_unary>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<derives_binary>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<derives_unary_binary>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<int(void)>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<int(*)(void)>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<int (::X::*)()>::result_type, int>::value, "has result_type" );
+  static_assert( is_same<reference_wrapper<int (::X::*)(float)>::result_type, int>::value, "has result_type" );
 }
 
 int main()
Index: testsuite/20_util/reference_wrapper/typedefs-3.cc
===================================================================
--- testsuite/20_util/reference_wrapper/typedefs-3.cc	(revision 0)
+++ testsuite/20_util/reference_wrapper/typedefs-3.cc	(revision 0)
@@ -0,0 +1,148 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 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/>.
+
+#include <functional>
+#include <type_traits>
+
+struct S { };
+
+struct S0
+{
+  typedef int argument_type;
+};
+
+struct S1
+{
+  typedef float first_argument_type;
+};
+
+struct S2
+{
+  typedef char second_argument_type;
+};
+
+struct S01 : S0, S1 { };
+struct S02 : S0, S2 { };
+struct S12 : S1, S2 { };
+
+struct S012 : S0, S1, S2 { };
+
+using std::__sfinae_types;
+using std::integral_constant;
+using std::remove_cv;
+
+_GLIBCXX_HAS_NESTED_TYPE(argument_type)
+_GLIBCXX_HAS_NESTED_TYPE(first_argument_type)
+_GLIBCXX_HAS_NESTED_TYPE(second_argument_type)
+
+template<typename T>
+  struct has_arg_type : __has_argument_type<T>
+  { };
+
+template<typename T>
+  struct has_1st_arg_type : __has_first_argument_type<T>
+  { };
+
+template<typename T>
+  struct has_2nd_arg_type : __has_second_argument_type<T>
+  { };
+
+template<typename T, bool = has_arg_type<T>::value>
+struct test_arg_type
+{
+  static_assert( !has_arg_type<std::reference_wrapper<T>>::value,
+      "reference_wrapper has no nested argument_type");
+};
+
+template<typename T>
+struct test_arg_type<T, true>
+{
+  typedef std::reference_wrapper<T> ref;
+
+  static_assert( has_arg_type<ref>::value,
+      "reference_wrapper has nested argument_type");
+
+  static_assert(
+      std::is_same< typename T::argument_type,
+                    typename ref::argument_type >::value,
+      "reference_wrapper has the correct argument_type");
+};
+
+template<typename T,
+         bool = has_1st_arg_type<T>::value && has_2nd_arg_type<T>::value>
+struct test_1st_2nd_arg_types
+{
+  typedef std::reference_wrapper<T> ref;
+
+  static_assert( !has_1st_arg_type<ref>::value,
+      "reference_wrapper has no nested first_argument_type");
+
+  static_assert( !has_2nd_arg_type<ref>::value,
+      "reference_wrapper has no nested second_argument_type");
+};
+
+template<typename T>
+struct test_1st_2nd_arg_types<T, true>
+{
+  typedef std::reference_wrapper<T> ref;
+
+  static_assert( has_1st_arg_type<ref>::value,
+      "reference_wrapper has nested first_argument_type");
+
+  static_assert( has_2nd_arg_type<ref>::value,
+      "reference_wrapper has nested second_argument_type");
+
+  static_assert(
+      std::is_same< typename T::first_argument_type,
+                    typename ref::first_argument_type>::value,
+      "reference_wrapper has correct first_argument_type");
+
+  static_assert(
+      std::is_same< typename T::second_argument_type,
+                    typename ref::second_argument_type>::value,
+      "reference_wrapper has correct second_argument_type");
+};
+
+
+template<typename T>
+  void test()
+  {
+    test_arg_type<T> t;
+    test_arg_type<const T> tc;
+    test_arg_type<volatile T> tv;
+    test_arg_type<const volatile T> tcv;
+    test_1st_2nd_arg_types<T> t12;
+    test_1st_2nd_arg_types<const T> t12c;
+    test_1st_2nd_arg_types<volatile T> t12v;
+    test_1st_2nd_arg_types<const volatile T> t12cv;
+  }
+
+int main()
+{
+  test<S>();
+  test<S0>();
+  test<S1>();
+  test<S2>();
+  test<S01>();
+  test<S02>();
+  test<S12>();
+  test<S012>();
+}
+
Index: testsuite/20_util/reference_wrapper/ref_neg.cc
===================================================================
--- testsuite/20_util/reference_wrapper/ref_neg.cc	(revision 0)
+++ testsuite/20_util/reference_wrapper/ref_neg.cc	(revision 0)
@@ -0,0 +1,44 @@ 
+// Copyright (C) 2011 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/>.
+
+// 20.8.3 Class template reference_wrapper
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <functional>
+
+struct X { };
+X rval();
+X&& rvalref();
+
+void test01()
+{
+  std::ref(1);          // { dg-error "deleted" }
+  std::cref(1);         // { dg-error "deleted" }
+  std::ref( int() );    // { dg-error "deleted" }
+  std::cref( int() );   // { dg-error "deleted" }
+  std::ref(rval());     // { dg-error "deleted" }
+  std::cref(rvalref()); // { dg-error "deleted" }
+}
+
+int main()
+{
+  test02();
+}
+
+// { dg-excess-errors "" }
Index: testsuite/20_util/reference_wrapper/invoke-2.cc
===================================================================
--- testsuite/20_util/reference_wrapper/invoke-2.cc	(revision 0)
+++ testsuite/20_util/reference_wrapper/invoke-2.cc	(revision 0)
@@ -0,0 +1,47 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile}
+// Copyright (C) 2011 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.4 function object return types [func.ret]
+#include <functional>
+
+struct X
+{
+    int f(int) { return 0; }
+    int i;
+};
+
+void test01()
+{
+  typedef int (X::*mfp)(int);
+  typedef int X::*mp;
+  mfp m = &X::f;
+  mp m2 = &X::i;
+  X x = { };
+  std::ref(m)(x, 1);
+  std::ref(m)(&x, 1);
+  int& i1 = std::ref(m2)(x);
+  int& i2 = std::ref(m2)(&x);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/20_util/declval/requirements/1_neg.cc
===================================================================
--- testsuite/20_util/declval/requirements/1_neg.cc	(revision 172708)
+++ testsuite/20_util/declval/requirements/1_neg.cc	(working copy)
@@ -19,7 +19,7 @@ 
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "static assertion failed" "" { target *-*-* } 1610 }
+// { dg-error "static assertion failed" "" { target *-*-* } 1598 }
 
 #include <utility>