PR c++/58407 - deprecated implicit copy ops.
gcc/c-family/ * c.opt (Wdeprecated-copy): New flag. gcc/cp/ * 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. libitm/ * beginend.cc (save): Disable -Werror=deprecated-copy. From-SVN: r260381
This commit is contained in:
parent
f07c223768
commit
b46b715d5b
17 changed files with 200 additions and 42 deletions
|
@ -1,3 +1,7 @@
|
|||
2018-05-18 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c.opt (Wdeprecated-copy): New flag.
|
||||
|
||||
2018-05-17 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* c-warn.c (overflow_warning): Do not use
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
2018-05-18 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2018-05-18 Cesar Philippidis <cesar@codesourcery.com>
|
||||
|
||||
PR c++/85782
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
29
gcc/testsuite/g++.dg/cpp0x/depr-copy1.C
Normal file
29
gcc/testsuite/g++.dg/cpp0x/depr-copy1.C
Normal file
|
@ -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 } }
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2018-05-17 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* beginend.cc (save): Disable -Werror=deprecated-copy.
|
||||
|
||||
2018-05-02 Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
PR testsuite/85106
|
||||
|
|
|
@ -431,7 +431,12 @@ GTM::gtm_transaction_cp::save(gtm_thread* tx)
|
|||
// Save everything that we might have to restore on restarts or aborts.
|
||||
jb = tx->jb;
|
||||
undolog_size = tx->undolog.size();
|
||||
|
||||
/* FIXME! Assignment of an aatree like alloc_actions is unsafe; if either
|
||||
*this or *tx is destroyed, the other ends up pointing to a freed node. */
|
||||
#pragma GCC diagnostic warning "-Wdeprecated-copy"
|
||||
alloc_actions = tx->alloc_actions;
|
||||
|
||||
user_actions_size = tx->user_actions.size();
|
||||
id = tx->id;
|
||||
prop = tx->prop;
|
||||
|
|
Loading…
Add table
Reference in a new issue