Patchwork [v3] more constexpr constructors for tuple, pair

login
register
mail settings
Submitter Benjamin Kosnik
Date Nov. 24, 2010, 4:42 p.m.
Message ID <20101124084218.568a0456@shotwell>
Download mbox | patch
Permalink /patch/72917/
State New
Headers show

Comments

Benjamin Kosnik - Nov. 24, 2010, 4:42 p.m.
This adds in more markup for constexpr for tuple and pair. In addition,
it adds post-3126 wording for defaulted copy constructors from N3140,
but does not bring in the defaulted move constructors.

I'm hoping that this is enough to hit the intent of DR 801, that tuple
and pair for simple enough types can be passed in registers. For IA64
C++ ABI, this has meant trivial destructors and copy constructors. In
any case, I started tracking this requirement in the dr801.cc test
cases.

tested x86_64/linux

-benjamin
H.J. Lu - Nov. 24, 2010, 7:48 p.m.
On Wed, Nov 24, 2010 at 8:42 AM, Benjamin Kosnik <bkoz@redhat.com> wrote:
>
> This adds in more markup for constexpr for tuple and pair. In addition,
> it adds post-3126 wording for defaulted copy constructors from N3140,
> but does not bring in the defaulted move constructors.
>
> I'm hoping that this is enough to hit the intent of DR 801, that tuple
> and pair for simple enough types can be passed in registers. For IA64
> C++ ABI, this has meant trivial destructors and copy constructors. In
> any case, I started tracking this requirement in the dr801.cc test
> cases.
>
> tested x86_64/linux

This may have caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46645

Patch

2010-11-24  Benjamin Kosnik  <bkoz@redhat.com>

	    * include/std/tuple: Mark more constructors constexpr.
	    * include/bits/stl_pair.h: Same.
	    * testsuite/20_util/tuple/requirements/dr801.cc: New.
	    * testsuite/20_util/pair/requirements/dr801.cc: New.
	    * testsuite/20_util/tuple/cons/constexpr.cc: Add cases for new
	    constexpr constructors.
	    * testsuite/20_util/pair/cons/constexpr.cc: Same.
	    * testsuite/20_util/pair/comparison_operators/constexpr.cc: New.

	    * testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust line number.

Index: include/std/tuple
===================================================================
--- include/std/tuple	(revision 167108)
+++ include/std/tuple	(working copy)
@@ -67,7 +67,7 @@ 
       constexpr _Head_base()
       : _Head() { }
 
-      _Head_base(const _Head& __h)
+      constexpr _Head_base(const _Head& __h)
       : _Head(__h) { }
 
       template<typename _UHead>
@@ -77,7 +77,8 @@ 
       _Head&       _M_head()       { return *this; }
       const _Head& _M_head() const { return *this; }
     
-      void _M_swap_impl(_Head&) { /* no-op */ }
+      void 
+      _M_swap_impl(_Head&) { /* no-op */ }
     };
 
   template<std::size_t _Idx, typename _Head>
@@ -86,7 +87,7 @@ 
       constexpr _Head_base()
       : _M_head_impl() { }
 
-      _Head_base(const _Head& __h)
+      constexpr _Head_base(const _Head& __h)
       : _M_head_impl(__h) { }
 
       template<typename _UHead>
@@ -151,7 +152,7 @@ 
       : _Inherited(), _Base() { }
 
       explicit 
-      _Tuple_impl(const _Head& __head, const _Tail&... __tail)
+      constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
       : _Inherited(__tail...), _Base(__head) { }
 
       template<typename _UHead, typename... _UTail> 
@@ -160,10 +161,10 @@ 
 	: _Inherited(std::forward<_UTail>(__tail)...),
 	  _Base(std::forward<_UHead>(__head)) { }
 
-      _Tuple_impl(const _Tuple_impl&) = default;
+      constexpr _Tuple_impl(const _Tuple_impl&) = default;
 
       _Tuple_impl(_Tuple_impl&& __in)
-      : _Inherited(std::move(__in._M_tail())),
+      : _Inherited(std::move(__in._M_tail())), 
 	_Base(std::forward<_Head>(__in._M_head())) { }
 
       template<typename... _UElements>
@@ -229,7 +230,7 @@ 
       : _Inherited() { }
 
       explicit
-      tuple(const _Elements&... __elements)
+      constexpr tuple(const _Elements&... __elements)
       : _Inherited(__elements...) { }
 
       template<typename... _UElements, typename = typename
@@ -239,7 +240,7 @@ 
         tuple(_UElements&&... __elements)
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
 
-      tuple(const tuple&) = default;
+      constexpr tuple(const tuple&) = default;
 
       tuple(tuple&& __in)
       : _Inherited(static_cast<_Inherited&&>(__in)) { }
@@ -314,7 +315,7 @@ 
       : _Inherited() { }
 
       explicit
-      tuple(const _T1& __a1, const _T2& __a2)
+      constexpr tuple(const _T1& __a1, const _T2& __a2)
       : _Inherited(__a1, __a2) { }
 
       template<typename _U1, typename _U2>
@@ -322,7 +323,7 @@ 
         tuple(_U1&& __a1, _U2&& __a2)
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
-      tuple(const tuple&) = default;
+      constexpr tuple(const tuple&) = default;
 
       tuple(tuple&& __in)
       : _Inherited(static_cast<_Inherited&&>(__in)) { }
@@ -412,7 +413,7 @@ 
       : _Inherited() { }
 
       explicit
-      tuple(const _T1& __a1)
+      constexpr tuple(const _T1& __a1)
       : _Inherited(__a1) { }
 
       template<typename _U1, typename = typename
@@ -421,14 +422,14 @@ 
         tuple(_U1&& __a1)
 	: _Inherited(std::forward<_U1>(__a1)) { }
 
-      tuple(const tuple&) = default;
+      constexpr tuple(const tuple&) = default;
 
       tuple(tuple&& __in)
       : _Inherited(static_cast<_Inherited&&>(__in)) { }
 
       template<typename _U1>
         tuple(const tuple<_U1>& __in)
-        : _Inherited(static_cast<const _Tuple_impl<0, _U1>&>(__in)) { }
+	: _Inherited(static_cast<const _Tuple_impl<0, _U1>&>(__in)) { }
 
       template<typename _U1>
         tuple(tuple<_U1>&& __in)
Index: include/bits/stl_pair.h
===================================================================
--- include/bits/stl_pair.h	(revision 167108)
+++ include/bits/stl_pair.h	(working copy)
@@ -98,63 +98,67 @@ 
       : first(), second() { }
 
       /** Two objects may be passed to a @c pair constructor to be copied.  */
-      pair(const _T1& __a, const _T2& __b)
+      _GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
       : first(__a), second(__b) { }
 
+      /** There is also a templated copy ctor for the @c pair class itself.  */
+      template<class _U1, class _U2>
+	_GLIBCXX_CONSTEXPR pair(const pair<_U1, _U2>& __p)
+	: first(__p.first), second(__p.second) { }
+
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
-      pair(const pair&) = default;
+      constexpr pair(const pair&) = default;
 
+      // Implicit.
+      // pair(pair&&) = default;
+
       // DR 811.
       template<class _U1, class = typename
 	       std::enable_if<std::is_convertible<_U1, _T1>::value>::type>
-        pair(_U1&& __x, const _T2& __y)
-	: first(std::forward<_U1>(__x)),
-	  second(__y) { }
+	pair(_U1&& __x, const _T2& __y)
+	: first(std::forward<_U1>(__x)), second(__y) { }
 
       template<class _U2, class = typename
 	       std::enable_if<std::is_convertible<_U2, _T2>::value>::type>
-        pair(const _T1& __x, _U2&& __y)
-	: first(__x),
-	  second(std::forward<_U2>(__y)) { }
+	pair(const _T1& __x, _U2&& __y)
+	: first(__x), second(std::forward<_U2>(__y)) { }
 
       template<class _U1, class _U2, class = typename
 	       std::enable_if<std::is_convertible<_U1, _T1>::value
 			      && std::is_convertible<_U2, _T2>::value>::type>
-        pair(_U1&& __x, _U2&& __y)
-	: first(std::forward<_U1>(__x)),
-	  second(std::forward<_U2>(__y)) { }
+	pair(_U1&& __x, _U2&& __y)
+	: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
 
-      template<class... _Args1, class... _Args2>
-        pair(piecewise_construct_t,
-	     tuple<_Args1...> __first_args,
-	     tuple<_Args2...> __second_args)
-	: first(__cons<first_type>(std::move(__first_args))),
-	  second(__cons<second_type>(std::move(__second_args))) { }
-#endif
-
-      /** There is also a templated copy ctor for the @c pair class itself.  */
       template<class _U1, class _U2>
-        pair(const pair<_U1, _U2>& __p)
-	: first(__p.first),
-	  second(__p.second) { }
-
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-      template<class _U1, class _U2>
-        pair(pair<_U1, _U2>&& __p)
+	pair(pair<_U1, _U2>&& __p)
 	: first(std::forward<_U1>(__p.first)),
 	  second(std::forward<_U2>(__p.second)) { }
 
+      template<class... _Args1, class... _Args2>
+	pair(piecewise_construct_t,
+	     tuple<_Args1...> __first, tuple<_Args2...> __second)
+	: first(__cons<first_type>(std::move(__first))),
+	  second(__cons<second_type>(std::move(__second))) { }
+
       pair&
+      operator=(const pair& __p)
+      {
+	first = __p.first;
+	second = __p.second;
+	return *this;
+      }
+
+      pair&
       operator=(pair&& __p)
-      { 
+      {
 	first = std::move(__p.first);
 	second = std::move(__p.second);
 	return *this;
       }
 
       template<class _U1, class _U2>
-        pair&
-        operator=(const pair<_U1, _U2>& __p)
+	pair&
+	operator=(const pair<_U1, _U2>& __p)
 	{
 	  first = __p.first;
 	  second = __p.second;
@@ -162,8 +166,8 @@ 
 	}
 
       template<class _U1, class _U2>
-        pair&
-        operator=(pair<_U1, _U2>&& __p)
+	pair&
+	operator=(pair<_U1, _U2>&& __p)
 	{
 	  first = std::move(__p.first);
 	  second = std::move(__p.second);
@@ -175,54 +179,54 @@ 
       {
 	using std::swap;
 	swap(first, __p.first);
-	swap(second, __p.second);	
+	swap(second, __p.second);
       }
 
     private:
       template<typename _Tp, typename... _Args>
-        static _Tp
-        __cons(tuple<_Args...>&&);
+	static _Tp
+	__cons(tuple<_Args...>&&);
 
       template<typename _Tp, typename... _Args, int... _Indexes>
-        static _Tp
-        __do_cons(tuple<_Args...>&&, const _Index_tuple<_Indexes...>&);
+	static _Tp
+	__do_cons(tuple<_Args...>&&, const _Index_tuple<_Indexes...>&);
 #endif
     };
 
   /// Two pairs of the same type are equal iff their members are equal.
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __x.first == __y.first && __x.second == __y.second; }
 
   /// <http://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html>
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __x.first < __y.first
 	     || (!(__y.first < __x.first) && __x.second < __y.second); }
 
   /// Uses @c operator== to find the result.
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__x == __y); }
 
   /// Uses @c operator< to find the result.
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __y < __x; }
 
   /// Uses @c operator< to find the result.
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__y < __x); }
 
   /// Uses @c operator< to find the result.
   template<class _T1, class _T2>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__x < __y); }
 
@@ -248,22 +252,23 @@ 
    */
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // 181.  make_pair() unintended behavior
-#ifndef __GXX_EXPERIMENTAL_CXX0X__
-  template<class _T1, class _T2>
-    inline pair<_T1, _T2>
-    make_pair(_T1 __x, _T2 __y)
-    { return pair<_T1, _T2>(__x, __y); }
-#else
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
   // NB: DR 706.
   template<class _T1, class _T2>
     inline pair<typename __decay_and_strip<_T1>::__type,
 		typename __decay_and_strip<_T2>::__type>
     make_pair(_T1&& __x, _T2&& __y)
     {
-      return pair<typename __decay_and_strip<_T1>::__type,
-	          typename __decay_and_strip<_T2>::__type>
-	(std::forward<_T1>(__x), std::forward<_T2>(__y));
+      typedef typename __decay_and_strip<_T1>::__type __ds_type1;
+      typedef typename __decay_and_strip<_T2>::__type __ds_type2;
+      typedef pair<__ds_type1, __ds_type2> 	      __pair_type;
+      return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
     }
+#else
+  template<class _T1, class _T2>
+    inline pair<_T1, _T2>
+    make_pair(_T1 __x, _T2 __y)
+    { return pair<_T1, _T2>(__x, __y); }
 #endif
 
 _GLIBCXX_END_NAMESPACE
Index: testsuite/20_util/tuple/cons/constexpr.cc
===================================================================
--- testsuite/20_util/tuple/cons/constexpr.cc	(revision 167108)
+++ testsuite/20_util/tuple/cons/constexpr.cc	(working copy)
@@ -23,7 +23,25 @@ 
 
 int main()
 {
-  __gnu_test::constexpr_default_constructible test;
-  test.operator()<std::tuple<int, int>>();
+  __gnu_test::constexpr_default_constructible test1;
+  test1.operator()<std::tuple<int, int>>();
+
+  __gnu_test::constexpr_single_value_constructible test2;
+  test2.operator()<std::tuple<int, int>, std::tuple<int, int>>();
+  //  test2.operator()<std::tuple<int, int>, std::pair<short, short>>();
+  //  test2.operator()<std::tuple<int>, std::tuple<short>>();
+  //  test2.operator()<std::tuple<int, int>, std::tuple<short, short>>();
+
+  // test 3
+  const int i1(129);
+  const int i2(6);
+  constexpr std::tuple<int, int> p3(i1, i2);
+
+  // test 4
+  const int i3(415);
+  const int i4(550);
+  const int i5(6414);
+  constexpr std::tuple<int, int, int, int, int> p4(i1, i2, i3, i4, i5);
+
   return 0;
 }
Index: testsuite/20_util/tuple/requirements/dr801.cc
===================================================================
--- testsuite/20_util/tuple/requirements/dr801.cc	(revision 0)
+++ testsuite/20_util/tuple/requirements/dr801.cc	(revision 0)
@@ -0,0 +1,52 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2010 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 <tuple>
+#include <type_traits>
+
+// DR 801, pair and tuple vs. "passed in registers"
+void test_trivial()
+{
+  // PODType, TType, NType, SLType, LType, NLType, LTypeDerived
+  typedef std::tuple<int, int> tuple_type;
+  // static_assert(std::is_literal_type<tuple_type>::value, "! literal");
+  static_assert(std::has_trivial_copy_constructor<tuple_type>::value,
+		"! triv copy");
+  static_assert(std::has_trivial_destructor<tuple_type>::value,
+		"! triv destructor");
+  // static_assert(std::is_standard_layout<tuple_type>::value,
+  //		   "! standard layout");
+
+  // Negative
+  /*
+  static_assert(std::has_trivial_default_constructor<tuple_type>::value,
+		"! triv default");
+  static_assert(std::has_trivial_copy_assign<tuple_type>::value,
+		"! triv assign");
+  static_assert(std::is_trivial<tuple_type>::value, "! triv");
+  static_assert(std::is_pod<tuple_type>::value, "! pod");
+  */
+}
+
+int main()
+{
+  test_trivial();
+  return 0;
+}
Index: testsuite/20_util/pair/cons/constexpr.cc
===================================================================
--- testsuite/20_util/pair/cons/constexpr.cc	(revision 167108)
+++ testsuite/20_util/pair/cons/constexpr.cc	(working copy)
@@ -23,7 +23,17 @@ 
 
 int main()
 {
-  __gnu_test::constexpr_default_constructible test;
-  test.operator()<std::pair<int, int>>();
+  __gnu_test::constexpr_default_constructible test1;
+  test1.operator()<std::pair<int, int>>();
+
+  __gnu_test::constexpr_single_value_constructible test2;
+  test2.operator()<std::pair<int, int>, std::pair<int, int>>();
+  test2.operator()<std::pair<int, int>, std::pair<short, short>>();
+
+  // test 3
+  const int i1(129);
+  const int i2(6);
+  constexpr std::pair<int, int> p3(i1, i2);
+
   return 0;
 }
Index: testsuite/20_util/pair/requirements/dr801.cc
===================================================================
--- testsuite/20_util/pair/requirements/dr801.cc	(revision 0)
+++ testsuite/20_util/pair/requirements/dr801.cc	(revision 0)
@@ -0,0 +1,52 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2010 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 <memory>
+#include <type_traits>
+
+// DR 801, pair and tuple vs. "passed in registers"
+void test_trivial()
+{
+  // PODType, TType, NType, SLType, LType, NLType, LTypeDerived
+  typedef std::pair<int, int> pair_type;
+  // static_assert(std::is_literal_type<pair_type>::value, "! literal");
+  static_assert(std::has_trivial_copy_constructor<pair_type>::value,
+		"! triv copy");
+  static_assert(std::has_trivial_destructor<pair_type>::value,
+		"! triv destructor");
+  // static_assert(std::is_standard_layout<pair_type>::value,
+  //               "! standard layout");
+
+  // Negative
+  /*
+  static_assert(std::has_trivial_default_constructor<pair_type>::value,
+		"! triv default");
+  static_assert(std::has_trivial_copy_assign<pair_type>::value,
+		"! triv assign");
+  static_assert(std::is_trivial<pair_type>::value, "! triv");
+  static_assert(std::is_pod<pair_type>::value, "! pod");
+  */
+}
+
+int main()
+{
+  test_trivial();
+  return 0;
+}
Index: testsuite/20_util/pair/comparison_operators/constexpr.cc
===================================================================
--- testsuite/20_util/pair/comparison_operators/constexpr.cc	(revision 0)
+++ testsuite/20_util/pair/comparison_operators/constexpr.cc	(revision 0)
@@ -0,0 +1,29 @@ 
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2010 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 <utility>
+#include <testsuite_common_types.h>
+
+int main()
+{
+  __gnu_test::constexpr_comparison_operators test;
+  test.operator()<std::pair<int, int>>();
+  return 0;
+}
Index: testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
===================================================================
--- testsuite/20_util/weak_ptr/comparison/cmp_neg.cc	(revision 167108)
+++ testsuite/20_util/weak_ptr/comparison/cmp_neg.cc	(working copy)
@@ -44,8 +44,8 @@ 
 // { dg-warning "note" "" { target *-*-* } 350 }
 // { dg-warning "note" "" { target *-*-* } 1082 }
 // { dg-warning "note" "" { target *-*-* } 465 }
-// { dg-warning "note" "" { target *-*-* } 580 }
+// { dg-warning "note" "" { target *-*-* } 581 }
 // { dg-warning "note" "" { target *-*-* } 1027 }
 // { dg-warning "note" "" { target *-*-* } 340 }
 // { dg-warning "note" "" { target *-*-* } 290 }
-// { dg-warning "note" "" { target *-*-* } 201 }
+// { dg-warning "note" "" { target *-*-* } 205 }