public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy
@ 2018-05-18 14:46 Jason Merrill
  2018-05-18 14:57 ` Jonathan Wakely
  0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2018-05-18 14:46 UTC (permalink / raw)
  To: gcc-patches List; +Cc: Jonathan Wakely

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

C++11 specified that the implicitly-declared copy constructor and
assignment operator are deprecated if one of them, or the destructor,
is user-provided.  This patch implements that; I've recently been
fixing some uses in the compiler of those deprecated copies.

Rather than bundle this into -Wdeprecated-declarations, I've
introduced a new -Wdeprecated-copy so that people can turn off this
specific deprecation if it causes problems for them; it certainly
complains about a lot of the G++ and libstdc++ testsuite.  But in this
patch it's enabled by -Wall.

We don't warn about elided copies from a temporary, as in that case no
actual copy is occurring; this is particularly important in the
context of C++17 mandatory copy elision, but makes sense under all
standards.

I've changed cp_warn_deprecated_use to handle all the checks for
whether we actually want the warning rather than repeat them at every
call site.

I needed to change build_aggr_init to only set TREE_USED if the
initialization has some effect so that libgomp.c++/ctor-5.C wouldn't
break with an error about threadprivate after the variable has been
used.

The second patch is some libstdc++ changes to avoid warnings from uses
of the standard library when this warning is on.  More are almost
certainly needed.  Jonathan, how would you like me to handle this WRT
the library?  Check in both patches and let you follow up as needed?
Hold off until you've had a chance to make the necessary library
changes?

Tested x86_64-pc-linux-gnu.

[-- Attachment #2: 58407.diff --]
[-- Type: text/x-patch, Size: 16023 bytes --]

commit a785eb5aa4898eff68af834a08d88577bf7685d9
Author: Jason Merrill <jason@redhat.com>
Date:   Tue May 15 17:42:34 2018 -0400

            PR c++/58407 - deprecated implicit copy ops.
    
            * call.c (build_over_call): Warn about deprecated trivial fns.
            * class.c (classtype_has_user_copy_or_dtor): New.
            (type_build_ctor_call): Check TREE_DEPRECATED.
            (type_build_dtor_call): Likewise.
            * decl2.c (cp_warn_deprecated_use): Move from tree.c.
            Add checks.  Return bool.  Handle -Wdeprecated-copy.
            (mark_used): Use it.
            * decl.c (grokdeclarator): Remove redundant checks.
            * typeck2.c (build_functional_cast): Likewise.
            * method.c (lazily_declare_fn): Mark deprecated copy ops.
            * init.c (build_aggr_init): Only set TREE_USED if there are
            side-effects.

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c48d6dced8d..5114543c128 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -464,6 +464,11 @@ Wdeprecated
 C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED) Var(warn_deprecated) Init(1) Warning
 Warn if a deprecated compiler feature, class, method, or field is used.
 
+Wdeprecated-copy
+C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wall)
+Mark implicitly-declared copy operations as deprecated if the class has a
+user-provided copy operation or destructor.
+
 Wdesignated-init
 C ObjC Var(warn_designated_init) Init(1) Warning
 Warn about positional initialization of structs requiring designated initializers.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4d04785f2b9..1df4d14dfe6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8168,21 +8168,30 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		    /* See unsafe_copy_elision_p.  */
 		    || DECL_BASE_CONSTRUCTOR_P (fn));
 
-      /* [class.copy]: the copy constructor is implicitly defined even if
-	 the implementation elided its use.  */
-      if (!trivial && !force_elide)
+      fa = argarray[0];
+      bool unsafe = unsafe_copy_elision_p (fa, arg);
+      bool eliding_temp = (TREE_CODE (arg) == TARGET_EXPR && !unsafe);
+
+      /* [class.copy]: the copy constructor is implicitly defined even if the
+	 implementation elided its use.  But don't warn about deprecation when
+	 eliding a temporary, as then no copy is actually performed.  */
+      warning_sentinel s (warn_deprecated_copy, eliding_temp);
+      if (force_elide)
+	/* The language says this isn't called.  */;
+      else if (!trivial)
 	{
 	  if (!mark_used (fn, complain) && !(complain & tf_error))
 	    return error_mark_node;
 	  already_used = true;
 	}
+      else
+	cp_warn_deprecated_use (fn, complain);
 
       /* If we're creating a temp and we already have one, don't create a
 	 new one.  If we're not creating a temp but we get one, use
 	 INIT_EXPR to collapse the temp into our target.  Otherwise, if the
 	 ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
 	 temp or an INIT_EXPR otherwise.  */
-      fa = argarray[0];
       if (is_dummy_object (fa))
 	{
 	  if (TREE_CODE (arg) == TARGET_EXPR)
@@ -8191,7 +8200,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	    return force_target_expr (DECL_CONTEXT (fn), arg, complain);
 	}
       else if ((trivial || TREE_CODE (arg) == TARGET_EXPR)
-	       && !unsafe_copy_elision_p (fa, arg))
+	       && !unsafe)
 	{
 	  tree to = cp_stabilize_reference (cp_build_fold_indirect_ref (fa));
 
@@ -8241,6 +8250,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
           TREE_NO_WARNING (val) = 1;
 	}
 
+      cp_warn_deprecated_use (fn, complain);
+
       return val;
     }
   else if (trivial_fn_p (fn))
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 306ee294d8a..4960b4b5593 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5171,6 +5171,40 @@ classtype_has_move_assign_or_move_ctor_p (tree t, bool user_p)
   return false;
 }
 
+/* If T, a class, has a user-provided copy constructor, copy assignment
+   operator, or destructor, returns that function.  Otherwise, null.  */
+
+tree
+classtype_has_user_copy_or_dtor (tree t)
+{
+  if (!CLASSTYPE_LAZY_COPY_CTOR (t))
+    for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
+      {
+	tree fn = *iter;
+	if (user_provided_p (fn) && copy_fn_p (fn))
+	  return fn;
+      }
+
+  if (!CLASSTYPE_LAZY_COPY_ASSIGN (t))
+    for (ovl_iterator iter (get_class_binding_direct
+			    (t, assign_op_identifier));
+	 iter; ++iter)
+      {
+	tree fn = *iter;
+	if (user_provided_p (fn) && copy_fn_p (fn))
+	  return fn;
+      }
+
+  if (!CLASSTYPE_LAZY_DESTRUCTOR (t))
+    {
+      tree fn = CLASSTYPE_DESTRUCTOR (t);
+      if (user_provided_p (fn))
+	return fn;
+    }
+
+  return NULL_TREE;
+}
+
 /* Nonzero if we need to build up a constructor call when initializing an
    object of this class, either because it has a user-declared constructor
    or because it doesn't have a default constructor (so we need to give an
@@ -5201,6 +5235,7 @@ type_build_ctor_call (tree t)
     {
       tree fn = *iter;
       if (!DECL_ARTIFICIAL (fn)
+	  || TREE_DEPRECATED (fn)
 	  || DECL_DELETED_FN (fn))
 	return true;
     }
@@ -5228,6 +5263,7 @@ type_build_dtor_call (tree t)
     {
       tree fn = *iter;
       if (!DECL_ARTIFICIAL (fn)
+	  || TREE_DEPRECATED (fn)
 	  || DECL_DELETED_FN (fn))
 	return true;
     }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index cab926028b8..b23a7c88863 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6103,6 +6103,7 @@ extern bool is_std_init_list			(tree);
 extern bool is_list_ctor			(tree);
 extern void validate_conversion_obstack		(void);
 extern void mark_versions_used			(tree);
+extern bool cp_warn_deprecated_use		(tree, tsubst_flags_t = tf_warning_or_error);
 extern tree get_function_version_dispatcher	(tree);
 
 /* in class.c */
@@ -6164,6 +6165,7 @@ extern bool trivial_default_constructor_is_constexpr (tree);
 extern bool type_has_constexpr_default_constructor (tree);
 extern bool type_has_virtual_destructor		(tree);
 extern bool classtype_has_move_assign_or_move_ctor_p (tree, bool user_declared);
+extern tree classtype_has_user_copy_or_dtor	(tree);
 extern bool type_build_ctor_call		(tree);
 extern bool type_build_dtor_call		(tree);
 extern void explain_non_literal_class		(tree);
@@ -7157,7 +7159,6 @@ extern tree cxx_copy_lang_qualifiers		(const_tree, const_tree);
 
 extern void cxx_print_statistics		(void);
 extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);
-extern void cp_warn_deprecated_use		(tree);
 
 /* in ptree.c */
 extern void cxx_print_xnode			(FILE *, tree, int);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 10e3079beed..f50812f9a87 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10388,18 +10388,12 @@ grokdeclarator (const cp_declarator *declarator,
       type = NULL_TREE;
       type_was_error_mark_node = true;
     }
-  /* If the entire declaration is itself tagged as deprecated then
-     suppress reports of deprecated items.  */
-  if (type && TREE_DEPRECATED (type)
-      && deprecated_state != DEPRECATED_SUPPRESS)
-    cp_warn_deprecated_use (type);
+  cp_warn_deprecated_use (type);
   if (type && TREE_CODE (type) == TYPE_DECL)
     {
       typedef_decl = type;
       type = TREE_TYPE (typedef_decl);
-      if (TREE_DEPRECATED (type)
-	  && DECL_ARTIFICIAL (typedef_decl)
-	  && deprecated_state != DEPRECATED_SUPPRESS)
+      if (DECL_ARTIFICIAL (typedef_decl))
 	cp_warn_deprecated_use (type);
     }
   /* No type at all: default to `int', and set DEFAULTED_INT
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 126356d5de4..b6e8e077bdc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5173,6 +5173,55 @@ maybe_instantiate_decl (tree decl)
     }
 }
 
+/* Maybe warn if DECL is deprecated, subject to COMPLAIN.  Returns whether or
+   not a warning was emitted.  */
+
+bool
+cp_warn_deprecated_use (tree decl, tsubst_flags_t complain)
+{
+  if (!(complain & tf_warning) || !decl
+      || deprecated_state == DEPRECATED_SUPPRESS)
+    return false;
+
+  if (!TREE_DEPRECATED (decl))
+    {
+      /* Perhaps this is a deprecated typedef.  */
+      if (TYPE_P (decl) && TYPE_NAME (decl))
+	decl = TYPE_NAME (decl);
+
+      if (!TREE_DEPRECATED (decl))
+	return false;
+    }
+
+  /* Don't warn within members of a deprecated type.  */
+  if (TYPE_P (decl)
+      && currently_open_class (decl))
+    return false;
+
+  bool warned = false;
+  if (cxx_dialect >= cxx11
+      && DECL_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+      && copy_fn_p (decl))
+    {
+      warned = warning (OPT_Wdeprecated_copy,
+			"implicitly-declared %qD is deprecated", decl);
+      if (warned)
+	{
+	  tree ctx = DECL_CONTEXT (decl);
+	  tree other = classtype_has_user_copy_or_dtor (ctx);
+	  inform (DECL_SOURCE_LOCATION (other),
+		  "because %qT has user-provided %qD",
+		  ctx, other);
+	}
+    }
+  else
+    warned = warn_deprecated_use (decl, NULL_TREE);
+
+  return warned;
+}
+
 /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
    If DECL is a specialization or implicitly declared class member,
    generate the actual definition.  Return false if something goes
@@ -5237,9 +5286,7 @@ mark_used (tree decl, tsubst_flags_t complain)
       return false;
     }
 
-  if (TREE_DEPRECATED (decl) && (complain & tf_warning)
-      && deprecated_state != DEPRECATED_SUPPRESS)
-    warn_deprecated_use (decl, NULL_TREE);
+  cp_warn_deprecated_use (decl, complain);
 
   /* We can only check DECL_ODR_USED on variables or functions with
      DECL_LANG_SPECIFIC set, and these are also the only decls that we
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d9fb0ea0086..b558742abf6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1733,11 +1733,6 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
       && !DIRECT_LIST_INIT_P (init))
     flags |= LOOKUP_ONLYCONVERTING;
 
-  if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
-      && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
-    /* Just know that we've seen something for this node.  */
-    TREE_USED (exp) = 1;
-
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
@@ -1748,6 +1743,12 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   TREE_READONLY (exp) = was_const;
   TREE_THIS_VOLATILE (exp) = was_volatile;
 
+  if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
+      && TREE_SIDE_EFFECTS (stmt_expr)
+      && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
+    /* Just know that we've seen something for this node.  */
+    TREE_USED (exp) = 1;
+
   return stmt_expr;
 }
 
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index ef0df7eb8d9..8e7590c5dbb 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -2394,8 +2394,19 @@ lazily_declare_fn (special_function_kind sfk, tree type)
      move assignment operator, the implicitly declared copy constructor is
      defined as deleted.... */
   if ((sfk == sfk_copy_assignment || sfk == sfk_copy_constructor)
-      && classtype_has_move_assign_or_move_ctor_p (type, true))
-    DECL_DELETED_FN (fn) = true;
+      && cxx_dialect >= cxx11)
+    {
+      if (classtype_has_move_assign_or_move_ctor_p (type, true))
+	DECL_DELETED_FN (fn) = true;
+      else if (classtype_has_user_copy_or_dtor (type))
+	/* The implicit definition of a copy constructor as defaulted is
+	   deprecated if the class has a user-declared copy assignment operator
+	   or a user-declared destructor. The implicit definition of a copy
+	   assignment operator as defaulted is deprecated if the class has a
+	   user-declared copy constructor or a user-declared destructor (15.4,
+	   15.8).  */
+	TREE_DEPRECATED (fn) = true;
+    }
 
   /* Destructors and assignment operators may be virtual.  */
   if (sfk == sfk_destructor
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index db81da91676..15b9697a63b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5398,19 +5398,6 @@ cp_tree_code_length (enum tree_code code)
     }
 }
 
-/* Wrapper around warn_deprecated_use that doesn't warn for
-   current_class_type.  */
-
-void
-cp_warn_deprecated_use (tree node)
-{
-  if (TYPE_P (node)
-      && current_class_type
-      && TYPE_MAIN_VARIANT (node) == current_class_type)
-    return;
-  warn_deprecated_use (node, NULL_TREE);
-}
-
 /* Implement -Wzero_as_null_pointer_constant.  Return true if the
    conditions for the warning hold, false otherwise.  */
 bool
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 682303ad7af..ad0774c6731 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -2064,9 +2064,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
     {
       type = TREE_TYPE (exp);
 
-      if (complain & tf_warning
-	  && TREE_DEPRECATED (type)
-	  && DECL_ARTIFICIAL (exp))
+      if (DECL_ARTIFICIAL (exp))
 	cp_warn_deprecated_use (type);
     }
   else
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 77e183c1608..d37ab6b3e0b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -213,7 +213,8 @@ in the following sections.
 -fvisibility-ms-compat @gol
 -fext-numeric-literals @gol
 -Wabi=@var{n}  -Wabi-tag  -Wconversion-null  -Wctor-dtor-privacy @gol
--Wdelete-non-virtual-dtor  -Wliteral-suffix  -Wmultiple-inheritance @gol
+-Wdelete-non-virtual-dtor -Wdeprecated-copy  -Wliteral-suffix @gol
+-Wmultiple-inheritance @gol
 -Wnamespaces  -Wnarrowing @gol
 -Wnoexcept  -Wnoexcept-type  -Wclass-memaccess @gol
 -Wnon-virtual-dtor  -Wreorder  -Wregister @gol
@@ -2900,6 +2901,14 @@ an instance of a derived class through a pointer to a base class if the
 base class does not have a virtual destructor.  This warning is enabled
 by @option{-Wall}.
 
+@item -Wdeprecated-copy @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-copy
+@opindex Wno-deprecated-copy
+Warn that the implicit declaration of a copy constructor or copy
+assignment operator is deprecated if the class has a user-provided
+copy constructor, copy assignment operator, or destructor, in C++11
+and up.  This warning is enabled by @option{-Wall}.
+
 @item -Wliteral-suffix @r{(C++ and Objective-C++ only)}
 @opindex Wliteral-suffix
 @opindex Wno-literal-suffix
diff --git a/gcc/testsuite/g++.dg/cpp0x/depr-copy1.C b/gcc/testsuite/g++.dg/cpp0x/depr-copy1.C
new file mode 100644
index 00000000000..d33c6dc667d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/depr-copy1.C
@@ -0,0 +1,29 @@
+/* [depr.impldec] The implicit definition of a copy constructor as defaulted is
+   deprecated if the class has a user-declared copy assignment operator or a
+   user-declared destructor. The implicit definition of a copy assignment
+   operator as defaulted is deprecated if the class has a user-declared copy
+   constructor or a user-declared destructor (15.4, 15.8). In a future revision
+   of this International Standard, these implicit definitions could become
+   deleted (11.4).  */
+
+// { dg-additional-options -Wdeprecated-copy }
+
+struct X
+{
+  X();
+  X(const X&);
+};
+struct A
+{
+  X x;
+  ~A();
+};
+
+void f(bool b)
+{
+  A a;
+  if (b)
+    throw A();			// Don't warn about elided copy
+  A a2 = A();			// Here either.
+  A a3 (a);			// { dg-warning "deprecated" "" { target c++11 } }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/warn6.C b/gcc/testsuite/g++.old-deja/g++.other/warn6.C
index 4325df74baa..b48e08406de 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/warn6.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/warn6.C
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "-W -Wall" }
+// { dg-options "-W -Wall -Wno-deprecated-copy" }
 
 // Copyright (C) 2001 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 2 Mar 2001 <nathan@codesourcery.com>

[-- Attachment #3: lib-depr-copy.diff --]
[-- Type: text/x-patch, Size: 8609 bytes --]

diff --git a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
index b0a1e864eff..0efefc65d49 100644
--- a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
@@ -5,4 +5,4 @@
 #include <new>
 __attribute__((visibility("hidden")))void*operator new(std::size_t); // { dg-warning "visibility attribute ignored" }
 
-// { dg-message "previous declaration" "" { target *-*-* } 120 }
+// { dg-message "previous declaration" "" { target *-*-* } 126 }
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 0a4eb55f611..2da499f1498 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -132,6 +132,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       allocator(const allocator& __a) throw()
       : __allocator_base<_Tp>(__a) { }
+#if __cplusplus >= 201103L
+      // Avoid implicit deprecation.
+      allocator& operator=(const allocator&) = default;
+#endif
 
       template<typename _Tp1>
 	allocator(const allocator<_Tp1>&) throw() { }
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 0d4390b2929..58a01c894c0 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -149,9 +149,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _Deque_iterator() _GLIBCXX_NOEXCEPT
       : _M_cur(), _M_first(), _M_last(), _M_node() { }
 
+#if __cplusplus < 201103L
+      // Conversion from iterator to const_iterator.
       _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
       : _M_cur(__x._M_cur), _M_first(__x._M_first),
 	_M_last(__x._M_last), _M_node(__x._M_node) { }
+#else
+      // Conversion from iterator to const_iterator.
+      template<typename _Iter,
+              typename = _Require<is_same<_Self, const_iterator>,
+                                  is_same<_Iter, iterator>>>
+       _Deque_iterator(const _Iter& __x) noexcept
+       : _M_cur(__x._M_cur), _M_first(__x._M_first),
+         _M_last(__x._M_last), _M_node(__x._M_node) { }
+
+      _Deque_iterator(const _Deque_iterator&) = default;
+      _Deque_iterator& operator=(const _Deque_iterator&) = default;
+#endif
 
       iterator
       _M_const_cast() const _GLIBCXX_NOEXCEPT
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 750b0c0f307..71d2afb1aeb 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -138,6 +138,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       reverse_iterator(const reverse_iterator& __x)
       : current(__x.current) { }
 
+#if __cplusplus >= 201103L
+      // Avoid implicit deprecation.
+      reverse_iterator& operator=(const reverse_iterator&) = default;
+#endif
+
       /**
        *  A %reverse_iterator across other types can be copied if the
        *  underlying %iterator can be converted to the type of @c current.
diff --git a/libstdc++-v3/include/ext/throw_allocator.h b/libstdc++-v3/include/ext/throw_allocator.h
index 5d9caa2bcae..2c7ef96025f 100644
--- a/libstdc++-v3/include/ext/throw_allocator.h
+++ b/libstdc++-v3/include/ext/throw_allocator.h
@@ -402,6 +402,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   struct condition_base
   {
+#if __cplusplus >= 201103L
+    condition_base() = default;
+
+    // Avoid implicit deprecation.
+    condition_base(const condition_base&) = default;
+    condition_base& operator=(const condition_base&) = default;
+#endif
     virtual ~condition_base() { };
   };
 
diff --git a/libstdc++-v3/include/std/stdexcept b/libstdc++-v3/include/std/stdexcept
index ddc056f752f..a9748ce8f04 100644
--- a/libstdc++-v3/include/std/stdexcept
+++ b/libstdc++-v3/include/std/stdexcept
@@ -150,6 +150,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit domain_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit domain_error(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    domain_error(const domain_error&) = default;
+    domain_error& operator=(const domain_error&) = default;
 #endif
     virtual ~domain_error() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -161,6 +164,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit invalid_argument(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit invalid_argument(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    invalid_argument(const invalid_argument&) = default;
+    invalid_argument& operator=(const invalid_argument&) = default;
 #endif
     virtual ~invalid_argument() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -173,6 +179,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit length_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit length_error(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    length_error(const length_error&) = default;
+    length_error& operator=(const length_error&) = default;
 #endif
     virtual ~length_error() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -185,6 +194,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit out_of_range(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit out_of_range(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    out_of_range(const out_of_range&) = default;
+    out_of_range& operator=(const out_of_range&) = default;
 #endif
     virtual ~out_of_range() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -233,6 +245,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit range_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit range_error(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    range_error(const range_error&) = default;
+    range_error& operator=(const range_error&) = default;
 #endif
     virtual ~range_error() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -244,6 +259,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit overflow_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit overflow_error(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    overflow_error(const overflow_error&) = default;
+    overflow_error& operator=(const overflow_error&) = default;
 #endif
     virtual ~overflow_error() _GLIBCXX_USE_NOEXCEPT;
   };
@@ -255,6 +273,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     explicit underflow_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 #if __cplusplus >= 201103L
     explicit underflow_error(const char*) _GLIBCXX_TXN_SAFE;
+    // Avoid implicit deprecation.
+    underflow_error(const underflow_error&) = default;
+    underflow_error& operator=(const underflow_error&) = default;
 #endif
     virtual ~underflow_error() _GLIBCXX_USE_NOEXCEPT;
   };
diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error
index 4918ef363d8..f0ef942bcd3 100644
--- a/libstdc++-v3/include/std/system_error
+++ b/libstdc++-v3/include/std/system_error
@@ -364,6 +364,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
       _M_code(__v, __ecat) { }
 
+#if __cplusplus >= 201103L
+    // Avoid implicit deprecation.
+    system_error (const system_error &) = default;
+    system_error &operator= (const system_error &) = default;
+#endif
+
     virtual ~system_error() noexcept;
 
     const error_code&
diff --git a/libstdc++-v3/libsupc++/exception.h b/libstdc++-v3/libsupc++/exception.h
index 3f1111d3e4b..8975ce3d55c 100644
--- a/libstdc++-v3/libsupc++/exception.h
+++ b/libstdc++-v3/libsupc++/exception.h
@@ -62,6 +62,11 @@ namespace std
   public:
     exception() _GLIBCXX_USE_NOEXCEPT { }
     virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
+#if __cplusplus >= 201103L
+    // Avoid implicit deprecation.
+    exception(const exception&) = default;
+    exception& operator=(const exception&) = default;
+#endif
 
     /** Returns a C-style character string describing the general cause
      *  of the current error.  */
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 99c769c48d6..068f17f0d21 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -56,6 +56,12 @@ namespace std
   public:
     bad_alloc() throw() { }
 
+#if __cplusplus >= 201103L
+    // Avoid implicit deprecation.
+    bad_alloc(const bad_alloc&) = default;
+    bad_alloc& operator=(const bad_alloc&) = default;
+#endif
+
     // This declaration is not useless:
     // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
     virtual ~bad_alloc() throw();

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy
  2018-05-18 14:46 RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy Jason Merrill
@ 2018-05-18 14:57 ` Jonathan Wakely
  2018-05-18 15:59   ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jonathan Wakely @ 2018-05-18 14:57 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On 18/05/18 10:29 -0400, Jason Merrill wrote:
>The second patch is some libstdc++ changes to avoid warnings from uses
>of the standard library when this warning is on.  More are almost
>certainly needed.  Jonathan, how would you like me to handle this WRT
>the library?  Check in both patches and let you follow up as needed?

Yes, please go ahead and commit the library patch, we'll deal with the
rest as needed (I'll give myself a TODO to test with -Wdeprecated-copy
and fix what I find).

I'm not sure we need the "Avoid implicit deprecation" comments. Adding
defaulted definitions is good style anyway, so needs no justification.
I'll make sure nobody removes them again in the name of cleaning up
unnecessary noise (which they aren't).

Did you change your mind about leaving the exception hierarchy without
the defautled ops, to get warnings for slicing?

I've just realised that our user-declared destructors on the exception
classes (which exist so we can control where the key function is
emitted) mean they have no implicit move ops. But the standard implies
they should have implicitly-declared move ops (because it doesn't
declare any special members for those classes). I'll open a bug.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy
  2018-05-18 14:57 ` Jonathan Wakely
@ 2018-05-18 15:59   ` Jason Merrill
  2018-05-18 16:06     ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2018-05-18 15:59 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches List

On Fri, May 18, 2018 at 10:51 AM, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 18/05/18 10:29 -0400, Jason Merrill wrote:
>>
>> The second patch is some libstdc++ changes to avoid warnings from uses
>> of the standard library when this warning is on.  More are almost
>> certainly needed.  Jonathan, how would you like me to handle this WRT
>> the library?  Check in both patches and let you follow up as needed?
>
>
> Yes, please go ahead and commit the library patch, we'll deal with the
> rest as needed (I'll give myself a TODO to test with -Wdeprecated-copy
> and fix what I find).
>
> I'm not sure we need the "Avoid implicit deprecation" comments. Adding
> defaulted definitions is good style anyway, so needs no justification.
> I'll make sure nobody removes them again in the name of cleaning up
> unnecessary noise (which they aren't).

OK.

> Did you change your mind about leaving the exception hierarchy without
> the defaulted ops, to get warnings for slicing?

Yes, because the warning also triggers in cases where we know the
dynamic type of the object, such as

exception e;
throw e;

I think a slicing warning should be separate.

Also because these functions are required by the standard, as below.

> I've just realised that our user-declared destructors on the exception
> classes (which exist so we can control where the key function is
> emitted) mean they have no implicit move ops. But the standard implies
> they should have implicitly-declared move ops (because it doesn't
> declare any special members for those classes). I'll open a bug.

Hmm, looks to me like it declares special members.

21.8.2 Class exception [exception]

namespace std {
  class exception {
  public:
    exception() noexcept;
    exception(const exception&) noexcept;
    exception& operator=(const exception&) noexcept;
    virtual ~exception();
    virtual const char* what() const noexcept;
  };
}

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy
  2018-05-18 15:59   ` Jason Merrill
@ 2018-05-18 16:06     ` Jason Merrill
  2018-05-18 16:14       ` Jonathan Wakely
  0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2018-05-18 16:06 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-patches List

On Fri, May 18, 2018 at 11:55 AM, Jason Merrill <jason@redhat.com> wrote:
> On Fri, May 18, 2018 at 10:51 AM, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On 18/05/18 10:29 -0400, Jason Merrill wrote:
>>>
>>> The second patch is some libstdc++ changes to avoid warnings from uses
>>> of the standard library when this warning is on.  More are almost
>>> certainly needed.  Jonathan, how would you like me to handle this WRT
>>> the library?  Check in both patches and let you follow up as needed?
>>
>>
>> Yes, please go ahead and commit the library patch, we'll deal with the
>> rest as needed (I'll give myself a TODO to test with -Wdeprecated-copy
>> and fix what I find).
>>
>> I'm not sure we need the "Avoid implicit deprecation" comments. Adding
>> defaulted definitions is good style anyway, so needs no justification.
>> I'll make sure nobody removes them again in the name of cleaning up
>> unnecessary noise (which they aren't).
>
> OK.
>
>> Did you change your mind about leaving the exception hierarchy without
>> the defaulted ops, to get warnings for slicing?
>
> Yes, because the warning also triggers in cases where we know the
> dynamic type of the object, such as
>
> exception e;
> throw e;
>
> I think a slicing warning should be separate.
>
> Also because these functions are required by the standard, as below.
>
>> I've just realised that our user-declared destructors on the exception
>> classes (which exist so we can control where the key function is
>> emitted) mean they have no implicit move ops. But the standard implies
>> they should have implicitly-declared move ops (because it doesn't
>> declare any special members for those classes). I'll open a bug.
>
> Hmm, looks to me like it declares special members.
>
> 21.8.2 Class exception [exception]
>
> namespace std {
>   class exception {
>   public:
>     exception() noexcept;
>     exception(const exception&) noexcept;
>     exception& operator=(const exception&) noexcept;
>     virtual ~exception();
>     virtual const char* what() const noexcept;
>   };
> }

...though this is not true of many of the derived exception classes.

Jason

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy
  2018-05-18 16:06     ` Jason Merrill
@ 2018-05-18 16:14       ` Jonathan Wakely
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2018-05-18 16:14 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On 18/05/18 11:58 -0400, Jason Merrill wrote:
>On Fri, May 18, 2018 at 11:55 AM, Jason Merrill <jason@redhat.com> wrote:
>> On Fri, May 18, 2018 at 10:51 AM, Jonathan Wakely <jwakely@redhat.com> wrote:
>>> On 18/05/18 10:29 -0400, Jason Merrill wrote:
>>>>
>>>> The second patch is some libstdc++ changes to avoid warnings from uses
>>>> of the standard library when this warning is on.  More are almost
>>>> certainly needed.  Jonathan, how would you like me to handle this WRT
>>>> the library?  Check in both patches and let you follow up as needed?
>>>
>>>
>>> Yes, please go ahead and commit the library patch, we'll deal with the
>>> rest as needed (I'll give myself a TODO to test with -Wdeprecated-copy
>>> and fix what I find).
>>>
>>> I'm not sure we need the "Avoid implicit deprecation" comments. Adding
>>> defaulted definitions is good style anyway, so needs no justification.
>>> I'll make sure nobody removes them again in the name of cleaning up
>>> unnecessary noise (which they aren't).
>>
>> OK.
>>
>>> Did you change your mind about leaving the exception hierarchy without
>>> the defaulted ops, to get warnings for slicing?
>>
>> Yes, because the warning also triggers in cases where we know the
>> dynamic type of the object, such as
>>
>> exception e;
>> throw e;
>>
>> I think a slicing warning should be separate.
>>
>> Also because these functions are required by the standard, as below.
>>
>>> I've just realised that our user-declared destructors on the exception
>>> classes (which exist so we can control where the key function is
>>> emitted) mean they have no implicit move ops. But the standard implies
>>> they should have implicitly-declared move ops (because it doesn't
>>> declare any special members for those classes). I'll open a bug.
>>
>> Hmm, looks to me like it declares special members.
>>
>> 21.8.2 Class exception [exception]
>>
>> namespace std {
>>   class exception {
>>   public:
>>     exception() noexcept;
>>     exception(const exception&) noexcept;
>>     exception& operator=(const exception&) noexcept;
>>     virtual ~exception();
>>     virtual const char* what() const noexcept;
>>   };
>> }
>
>...though this is not true of many of the derived exception classes.

Right. std::exception has no data members anyway, so moving is the
same as copying. For the derived types the standard declares them
like:

namespace std {
  class logic_error : public exception {
  public:
    explicit logic_error(const string& what_arg);
    explicit logic_error(const char* what_arg);
  };
}

But we define:

  class logic_error : public exception
  {
    [...]

    virtual ~logic_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;

    [...]
  };

And this means there is no move constructor or move assignment operator.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-05-18 16:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-18 14:46 RFC (libstdc++): C++ PATCH for c++/58407, C++11 deprecation of implicit copy Jason Merrill
2018-05-18 14:57 ` Jonathan Wakely
2018-05-18 15:59   ` Jason Merrill
2018-05-18 16:06     ` Jason Merrill
2018-05-18 16:14       ` Jonathan Wakely

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).