public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ville Voutilainen <ville.voutilainen@gmail.com>
To: Paolo Carlini <paolo.carlini@oracle.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	libstdc++@gcc.gnu.org
Subject: Re: [v3 PATCH] Make the default constructors of tuple and pair conditionally explicit.
Date: Tue, 03 Nov 2015 05:02:00 -0000	[thread overview]
Message-ID: <CAFk2RUaw+ykUmNFtZ-FsXAz+Zf_=uh9YWwo1oUaps0rB7JeyDQ@mail.gmail.com> (raw)
In-Reply-To: <5637D079.1070906@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 2095 bytes --]

On 2 November 2015 at 23:07, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Great, thanks a lot. Thinking more about this detail, I wonder if we should
> therefore apply the below too? Anything I'm missing?

Tested again on Linux-PPC64. Ok for trunk?

2015-11-03  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Make the default constructors of tuple and pair conditionally explicit.
    * include/std/type_traits (is_unsigned, __is_array_unknown_bounds,
    __is_default_constructible_atom, __is_default_constructible_safe,
    __is_direct_constructible_new_safe, __is_direct_constructible_ref_cast,
        __is_nt_default_constructible_impl, is_nothrow_default_constructible,
        is_nothrow_constructible, is_nothrow_assignable,
        is_trivially_constructible, is_trivially_copy_constructible,
        is_trivially_move_constructible, is_trivially_assignable,
        is_trivially_copy_assignable, is_trivially_move_assignable,
        is_trivially_destructible): Simplify.
    * include/std/type_traits (
    __do_is_implicitly_default_constructible_impl,
    __is_implicitly_default_constructible_impl,
    __is_implicitly_default_constructible_safe,
    __is_implicitly_default_constructible): New.
    * include/bits/stl_pair.h (pair::pair()): Use it.
    * include/std/tuple (tuple<_T1, _T2>::tuple): Use it.
    * include/std/tuple (_ImplicitlyDefaultConstructibleTuple): New.
    * include/std/tuple (tuple<_Types...>::tuple()): Use it.
    * testsuite/20_util/declval/requirements/1_neg.cc: Adjust.
    * testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc:
New.
    * testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc:
Likewise.
    * testsuite/20_util/is_implicitly_default_constructible/value.cc: Likewise.
    * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust.
    * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise.
    * testsuite/20_util/pair/cons/explicit_construct.cc: Likewise.
    * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise.

[-- Attachment #2: conditional-explicit-default-ctors-pair-tuple5.diff --]
[-- Type: text/plain, Size: 26947 bytes --]

diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index a5a7898..dfcd357 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -141,13 +141,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
                 typename enable_if<__and_<
-                                     is_default_constructible<_U1>,
-                                     is_default_constructible<_U2>>
+                                     __is_implicitly_default_constructible<_U1>,
+                                     __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 #endif
       _GLIBCXX_CONSTEXPR pair()
       : first(), second() { }
 
+#if __cplusplus >= 201103L
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<__and_<
+                       is_default_constructible<_U1>,
+                       is_default_constructible<_U2>,
+                       __not_<
+                         __and_<__is_implicitly_default_constructible<_U1>,
+                                __is_implicitly_default_constructible<_U2>>>>
+                                   ::value, bool>::type = false>
+      explicit constexpr pair()
+      : first(), second() { }
+#endif
+
       /** Two objects may be passed to a @c pair constructor to be copied.  */
 #if __cplusplus < 201103L
       pair(const _T1& __a, const _T2& __b)
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 8af01f4..e6c32b3 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -551,16 +551,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         {
           return __and_<is_default_constructible<_Elements>...>::value;
         }
+        static constexpr bool _ImplicitlyDefaultConstructibleTuple()
+        {
+          return __and_<__is_implicitly_default_constructible<_Elements>...>
+            ::value;
+        }
       };
 
     public:
       template<typename _Dummy = void,
                typename enable_if<_TC2<_Dummy>::
-                                    _DefaultConstructibleTuple(),
+                                    _ImplicitlyDefaultConstructibleTuple(),
                                   bool>::type = true>
       constexpr tuple()
       : _Inherited() { }
 
+      template<typename _Dummy = void,
+               typename enable_if<_TC2<_Dummy>::
+                                    _DefaultConstructibleTuple()
+                                  &&
+                                  !_TC2<_Dummy>::
+                                    _ImplicitlyDefaultConstructibleTuple(),
+                                  bool>::type = false>
+      explicit constexpr tuple()
+      : _Inherited() { }
+
       // Shortcut for the cases where constructors taking _Elements...
       // need to be constrained.
       template<typename _Dummy> using _TCC =
@@ -837,13 +852,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template <typename _U1 = _T1,
                 typename _U2 = _T2,
                 typename enable_if<__and_<
-                                     is_default_constructible<_U1>,
-                                     is_default_constructible<_U2>>
+                                     __is_implicitly_default_constructible<_U1>,
+                                     __is_implicitly_default_constructible<_U2>>
                                    ::value, bool>::type = true>
 
       constexpr tuple()
       : _Inherited() { }
 
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<
+                  __and_<
+                    is_default_constructible<_U1>,
+                    is_default_constructible<_U2>,
+                    __not_<
+                      __and_<__is_implicitly_default_constructible<_U1>,
+                             __is_implicitly_default_constructible<_U2>>>>
+                  ::value, bool>::type = false>
+
+      explicit constexpr tuple()
+      : _Inherited() { }
+
       // Shortcut for the cases where constructors taking _T1, _T2
       // need to be constrained.
       template<typename _Dummy> using _TCC =
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index e08131b..7448d5b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -715,7 +715,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_unsigned
   template<typename _Tp>
     struct is_unsigned
-    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
     { };
 
 
@@ -744,7 +744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_array_unknown_bounds
-    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
     { };
     
   // In N3290 is_destructible does not say anything about function
@@ -862,7 +862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct __is_default_constructible_atom
     : public __and_<__not_<is_void<_Tp>>,
-                    __is_default_constructible_impl<_Tp>>::type
+                    __is_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, bool = is_array<_Tp>::value>
@@ -877,7 +877,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_default_constructible_safe<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -957,7 +957,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Arg>
     struct __is_direct_constructible_new_safe
     : public __and_<is_destructible<_Tp>,
-                    __is_direct_constructible_impl<_Tp, _Arg>>::type
+                    __is_direct_constructible_impl<_Tp, _Arg>>
     { };
 
   template<typename, typename>
@@ -1029,7 +1029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __and_<__is_static_castable<_Arg, _Tp>,
                     __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
                                  __is_lvalue_to_rvalue_ref<_Arg, _Tp>
-                   >>>::type
+                   >>>
     { };
 
   template<typename _Tp, typename _Arg>
@@ -1144,7 +1144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_nt_default_constructible_impl<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
 		    __is_nt_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -1156,7 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_nothrow_default_constructible
     : public __and_<is_default_constructible<_Tp>,
-                    __is_nt_default_constructible_impl<_Tp>>::type
+                    __is_nt_default_constructible_impl<_Tp>>
     { };
 
   template<typename _Tp, typename... _Args>
@@ -1179,7 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename... _Args>
     struct is_nothrow_constructible
     : public __and_<is_constructible<_Tp, _Args...>,
-		    __is_nt_constructible_impl<_Tp, _Args...>>::type
+		    __is_nt_constructible_impl<_Tp, _Args...>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1285,7 +1285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Up>
     struct is_nothrow_assignable
     : public __and_<is_assignable<_Tp, _Up>,
-		    __is_nt_assignable_impl<_Tp, _Up>>::type
+		    __is_nt_assignable_impl<_Tp, _Up>>
     { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
@@ -1328,7 +1328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename... _Args>
     struct is_trivially_constructible
     : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Args...)>>::type
+			__is_trivially_constructible(_Tp, _Args...)>>
     { };
   
   /// is_trivially_default_constructible
@@ -1337,12 +1337,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public is_trivially_constructible<_Tp>::type
     { };
 
+  struct __do_is_implicitly_default_constructible_impl
+  {
+    template <typename _Tp>
+    static void __helper(const _Tp&);
+
+    template <typename _Tp>
+    static true_type __test(const _Tp&,
+                            decltype(__helper<const _Tp&>({}))* = 0);
+
+    static false_type __test(...);
+  };
+
+  template<typename _Tp>
+    struct __is_implicitly_default_constructible_impl
+      : public __do_is_implicitly_default_constructible_impl
+  {
+    typedef decltype(__test(declval<_Tp>())) type;
+  };
+
+  template<typename _Tp>
+    struct __is_implicitly_default_constructible_safe
+      : public __is_implicitly_default_constructible_impl<_Tp>::type
+  { };
+
+  template <typename _Tp>
+    struct __is_implicitly_default_constructible
+      : public __and_<is_default_constructible<_Tp>,
+                      __is_implicitly_default_constructible_safe<_Tp>>
+  { };
+
   /// is_trivially_copy_constructible
   template<typename _Tp>
     struct is_trivially_copy_constructible
     : public __and_<is_copy_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, const _Tp&)>>::type
+			__is_trivially_constructible(_Tp, const _Tp&)>>
     { };
   
   /// is_trivially_move_constructible
@@ -1350,7 +1380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_move_constructible
     : public __and_<is_move_constructible<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_constructible(_Tp, _Tp&&)>>::type
+			__is_trivially_constructible(_Tp, _Tp&&)>>
     { };
 
   /// is_trivially_assignable
@@ -1358,7 +1388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_assignable
     : public __and_<is_assignable<_Tp, _Up>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp, _Up)>>::type
+			__is_trivially_assignable(_Tp, _Up)>>
     { };
 
   /// is_trivially_copy_assignable
@@ -1366,7 +1396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_copy_assignable
     : public __and_<is_copy_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, const _Tp&)>>::type
+			__is_trivially_assignable(_Tp&, const _Tp&)>>
     { };
 
   /// is_trivially_move_assignable
@@ -1374,14 +1404,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_trivially_move_assignable
     : public __and_<is_move_assignable<_Tp>, 
 		    integral_constant<bool,
-			__is_trivially_assignable(_Tp&, _Tp&&)>>::type
+			__is_trivially_assignable(_Tp&, _Tp&&)>>
     { };
 
   /// is_trivially_destructible
   template<typename _Tp>
     struct is_trivially_destructible
     : public __and_<is_destructible<_Tp>, integral_constant<bool,
-			      __has_trivial_destructor(_Tp)>>::type
+			      __has_trivial_destructor(_Tp)>>
     { };
 
   /// has_trivial_default_constructor (temporary legacy)
diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
index 2723e5c..4e7deda 100644
--- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
@@ -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 *-*-* } 2209 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2239 }
 
 #include <utility>
 
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..acc9f37
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/explicit_instantiation.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 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 <type_traits>
+
+namespace std
+{
+  typedef short test_type;
+  template struct std::__is_implicitly_default_constructible<test_type>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc
new file mode 100644
index 0000000..234b06c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/requirements/typedefs.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 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 <type_traits>
+
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::__is_implicitly_default_constructible<int>          test_type;
+  typedef test_type::value_type                     value_type;
+  typedef test_type::type                           type;
+  typedef test_type::type::value_type               type_value_type;
+  typedef test_type::type::type                     type_type;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc
new file mode 100644
index 0000000..aff4955
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicitly_default_constructible/value.cc
@@ -0,0 +1,44 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2015 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 <type_traits>
+
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
+void test01()
+{
+  using std::__is_implicitly_default_constructible;
+  // Positive tests.
+  static_assert(__is_implicitly_default_constructible<int>::value, "");
+  // Negative tests.
+  static_assert(!__is_implicitly_default_constructible<int&>::value, "");
+  static_assert(!__is_implicitly_default_constructible<
+                ExplicitDefault>::value, "");
+  static_assert(!__is_implicitly_default_constructible<
+                ExplicitDefaultDefault>::value, "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index 507930d..8e5fe53 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,4 +48,4 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 40 }
 // { dg-error "required from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1874 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1904 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index 608fd1a..4cd0311 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
 // { dg-error "required from here" "" { target *-*-* } 40 }
 // { dg-error "required from here" "" { target *-*-* } 42 }
 
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1770 }
-// { dg-error "declaration of" "" { target *-*-* } 1727 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1800 }
+// { dg-error "declaration of" "" { target *-*-* } 1757 }
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
index 50edda9..ac1dc7e 100644
--- a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -26,6 +26,16 @@ struct Explicit
   explicit Explicit(int) {}
 };
 
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
 std::pair<int, int> f1() {return {1,2};}
 
 std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
@@ -72,6 +82,20 @@ void f6(std::pair<Explicit, Explicit>) {}
 
 void f7(std::pair<long, long>) {}
 
+std::pair<ExplicitDefault, int> f8()
+{
+  return {}; // { dg-error "explicit" }
+}
+
+std::pair<ExplicitDefaultDefault, int> f9()
+{
+  return {}; // { dg-error "explicit" }
+}
+
+void f10(std::pair<ExplicitDefault, int>) {}
+
+void f11(std::pair<ExplicitDefaultDefault, int>) {}
+
 void test_arg_passing()
 {
   f6(v0); // { dg-error "could not convert" }
@@ -84,6 +108,10 @@ void test_arg_passing()
   f7({1,2});
   f7(std::pair<int, int>{});
   f7(std::pair<long, long>{});
+  f10({}); // { dg-error "explicit" }
+  f11({}); // { dg-error "explicit" }
+  f10(std::pair<ExplicitDefault, int>{});
+  f11(std::pair<ExplicitDefaultDefault, int>{});
 }
 
 struct MoveOnly
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
index 114a490..4d97cfb 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -28,13 +28,26 @@ struct Explicit
   explicit Explicit(int) {}
 };
 
+struct ExplicitDefault
+{
+  explicit ExplicitDefault() {}
+};
+
+struct ExplicitDefaultDefault
+{
+  explicit ExplicitDefaultDefault() = default;
+};
+
 std::tuple<int> f1a() {return {1};}
 std::tuple<int, int> f1b() {return {1,2};}
 std::tuple<int, int, int> f1c() {return {1,2,3};}
 
-std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
-std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
-std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
+std::tuple<Explicit> f2_a()
+{return {1};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> f2_b()
+{return {1,2};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> f2_c()
+{return {1,2,3};} // { dg-error "explicit" }
 
 std::tuple<long> f3_a() {return std::tuple<int>{1};}
 std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
@@ -57,6 +70,24 @@ std::tuple<long> f5_a() {return {1};}
 std::tuple<long, long> f5_b() {return {1,2};}
 std::tuple<long, long, long> f5_c() {return {1,2,3};}
 
+std::tuple<ExplicitDefault> f6_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault> f6_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, ExplicitDefault, ExplicitDefault> f6_c()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> f6_d()
+{return {};} // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> f7_a()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, ExplicitDefaultDefault> f7_b()
+{return {};} // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault,
+           ExplicitDefaultDefault,
+           ExplicitDefaultDefault> f7_c()
+{return {};} // { dg-error "explicit" }
+
 std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
 std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
 std::tuple<Explicit, Explicit> fp3()
@@ -163,7 +194,7 @@ std::tuple<long, long, long>
   v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
 
 std::tuple<Explicit> v32_a
-  = {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
+  = {std::allocator_arg, std::allocator<int>{ }, 1}; // { dg-error "explicit" }
 std::tuple<Explicit, Explicit> v32_b
   = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
 std::tuple<Explicit, Explicit, Explicit> v32_c
@@ -199,7 +230,19 @@ std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
 std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
 
 std::tuple<Explicit, Explicit> v44
-= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
+= {std::allocator_arg, std::allocator<int>{ }, v20}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault> v45_a{};
+std::tuple<ExplicitDefault, int> v45_b{};
+
+std::tuple<ExplicitDefault> v46_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefault, int> v46_b = {}; // { dg-error "explicit" }
+
+std::tuple<ExplicitDefaultDefault> v47_a{};
+std::tuple<ExplicitDefaultDefault, int> v47_b{};
+
+std::tuple<ExplicitDefaultDefault> v48_a = {}; // { dg-error "explicit" }
+std::tuple<ExplicitDefaultDefault, int> v48_b = { }; // { dg-error "explicit" }
+
 
 struct DeletedCopy
 {
@@ -225,58 +268,73 @@ std::tuple<int, int, Sanity> v50(std::allocator_arg,
                                  std::allocator<Sanity>{},
                                  3, 4, {42});
 
-void f6_a(std::tuple<Explicit>) {}
-void f6_b(std::tuple<Explicit, Explicit>) {}
-void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
+void f8_a(std::tuple<Explicit>) {}
+void f8_b(std::tuple<Explicit, Explicit>) {}
+void f8_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f9_a(std::tuple<long>) {}
+void f9_b(std::tuple<long, long>) {}
+void f9_c(std::tuple<long, long, long>) {}
+
+void f10_a(std::tuple<ExplicitDefault>) {}
+void f10_b(std::tuple<ExplicitDefault, int>) {}
 
-void f7_a(std::tuple<long>) {}
-void f7_b(std::tuple<long, long>) {}
-void f7_c(std::tuple<long, long, long>) {}
+void f11_a(std::tuple<ExplicitDefaultDefault>) {}
+void f11_b(std::tuple<ExplicitDefaultDefault, int>) {}
 
 void test_arg_passing()
 {
-  f6_a(v0_a); // { dg-error "could not convert" }
-  f6_b(v0_b); // { dg-error "could not convert" }
-  f6_c(v0_c); // { dg-error "could not convert" }
-  f6_b(v20); // { dg-error "could not convert" }
-
-  f6_a(v1_a);
-  f6_b(v1_b);
-  f6_c(v1_c);
-
-  f6_a({1}); // { dg-error "explicit" }
-  f6_b({1,2}); // { dg-error "explicit" }
-  f6_c({1,2,3}); // { dg-error "explicit" }
-
-  f6_a(std::tuple<Explicit>{});
-  f6_b(std::tuple<Explicit, Explicit>{});
-  f6_c(std::tuple<Explicit, Explicit, Explicit>{});
-
-  f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
-  f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
-  f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
-  f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
-
-  f7_a(v0_a);
-  f7_b(v0_b);
-  f7_c(v0_c);
-  f7_b(v20);
-
-  f7_a(v6_a);
-  f7_b(v6_b);
-  f7_c(v6_c);
-
-  f7_a({1});
-  f7_b({1,2});
-  f7_c({1,2,3});
-
-  f7_a(std::tuple<int>{});
-  f7_b(std::tuple<int, int>{});
-  f7_c(std::tuple<int, int, int>{});
-  f7_b(std::pair<int, int>{});
-
-
-  f7_a(std::tuple<long>{});
-  f7_b(std::tuple<long, long>{});
-  f7_c(std::tuple<long, long, long>{});
+  f8_a(v0_a); // { dg-error "could not convert" }
+  f8_b(v0_b); // { dg-error "could not convert" }
+  f8_c(v0_c); // { dg-error "could not convert" }
+  f8_b(v20); // { dg-error "could not convert" }
+
+  f8_a(v1_a);
+  f8_b(v1_b);
+  f8_c(v1_c);
+
+  f8_a({1}); // { dg-error "explicit" }
+  f8_b({1,2}); // { dg-error "explicit" }
+  f8_c({1,2,3}); // { dg-error "explicit" }
+
+  f8_a(std::tuple<Explicit>{});
+  f8_b(std::tuple<Explicit, Explicit>{});
+  f8_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+  f8_a(std::tuple<int>{}); // { dg-error "could not convert" }
+  f8_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+  f8_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+  f8_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+  f9_a(v0_a);
+  f9_b(v0_b);
+  f9_c(v0_c);
+  f9_b(v20);
+
+  f9_a(v6_a);
+  f9_b(v6_b);
+  f9_c(v6_c);
+
+  f9_a({1});
+  f9_b({1,2});
+  f9_c({1,2,3});
+
+  f9_a(std::tuple<int>{});
+  f9_b(std::tuple<int, int>{});
+  f9_c(std::tuple<int, int, int>{});
+  f9_b(std::pair<int, int>{});
+
+  f9_a(std::tuple<long>{});
+  f9_b(std::tuple<long, long>{});
+  f9_c(std::tuple<long, long, long>{});
+
+  f10_a({}); // { dg-error "explicit" }
+  f10_b({}); // { dg-error "explicit" }
+  f11_a({}); // { dg-error "explicit" }
+  f11_b({}); // { dg-error "explicit" }
+
+  f10_a(std::tuple<ExplicitDefault>{});
+  f10_b(std::tuple<ExplicitDefault, int>{});
+  f11_a(std::tuple<ExplicitDefaultDefault>{});
+  f11_b(std::tuple<ExplicitDefaultDefault, int>{});
 }

  reply	other threads:[~2015-11-03  5:02 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-01  3:27 Ville Voutilainen
2015-11-02 15:19 ` Paolo Carlini
2015-11-02 17:00   ` Ville Voutilainen
2015-11-02 19:20     ` Paolo Carlini
2015-11-02 20:20       ` Ville Voutilainen
2015-11-02 21:07         ` Paolo Carlini
2015-11-03  5:02           ` Ville Voutilainen [this message]
2015-11-03  8:32             ` Paolo Carlini
2015-11-03 14:43           ` Jonathan Wakely
2015-11-03 14:49             ` Ville Voutilainen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAFk2RUaw+ykUmNFtZ-FsXAz+Zf_=uh9YWwo1oUaps0rB7JeyDQ@mail.gmail.com' \
    --to=ville.voutilainen@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=libstdc++@gcc.gnu.org \
    --cc=paolo.carlini@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).