Skip to content

Commit b46b715

Browse files
jicamaJason Merrill
authored andcommitted
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
1 parent f07c223 commit b46b715

File tree

17 files changed

+200
-42
lines changed

17 files changed

+200
-42
lines changed

gcc/c-family/ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2018-05-18 Jason Merrill <[email protected]>
2+
3+
* c.opt (Wdeprecated-copy): New flag.
4+
15
2018-05-17 Martin Liska <[email protected]>
26

37
* c-warn.c (overflow_warning): Do not use

gcc/c-family/c.opt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,11 @@ Wdeprecated
464464
C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED) Var(warn_deprecated) Init(1) Warning
465465
Warn if a deprecated compiler feature, class, method, or field is used.
466466

467+
Wdeprecated-copy
468+
C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wall)
469+
Mark implicitly-declared copy operations as deprecated if the class has a
470+
user-provided copy operation or destructor.
471+
467472
Wdesignated-init
468473
C ObjC Var(warn_designated_init) Init(1) Warning
469474
Warn about positional initialization of structs requiring designated initializers.

gcc/cp/ChangeLog

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
2018-05-18 Jason Merrill <[email protected]>
2+
3+
PR c++/58407 - deprecated implicit copy ops.
4+
* call.c (build_over_call): Warn about deprecated trivial fns.
5+
* class.c (classtype_has_user_copy_or_dtor): New.
6+
(type_build_ctor_call): Check TREE_DEPRECATED.
7+
(type_build_dtor_call): Likewise.
8+
* decl2.c (cp_warn_deprecated_use): Move from tree.c.
9+
Add checks. Return bool. Handle -Wdeprecated-copy.
10+
(mark_used): Use it.
11+
* decl.c (grokdeclarator): Remove redundant checks.
12+
* typeck2.c (build_functional_cast): Likewise.
13+
* method.c (lazily_declare_fn): Mark deprecated copy ops.
14+
* init.c (build_aggr_init): Only set TREE_USED if there are
15+
side-effects.
16+
117
2018-05-18 Cesar Philippidis <[email protected]>
218

319
PR c++/85782

gcc/cp/call.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8168,21 +8168,30 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
81688168
/* See unsafe_copy_elision_p. */
81698169
|| DECL_BASE_CONSTRUCTOR_P (fn));
81708170

8171-
/* [class.copy]: the copy constructor is implicitly defined even if
8172-
the implementation elided its use. */
8173-
if (!trivial && !force_elide)
8171+
fa = argarray[0];
8172+
bool unsafe = unsafe_copy_elision_p (fa, arg);
8173+
bool eliding_temp = (TREE_CODE (arg) == TARGET_EXPR && !unsafe);
8174+
8175+
/* [class.copy]: the copy constructor is implicitly defined even if the
8176+
implementation elided its use. But don't warn about deprecation when
8177+
eliding a temporary, as then no copy is actually performed. */
8178+
warning_sentinel s (warn_deprecated_copy, eliding_temp);
8179+
if (force_elide)
8180+
/* The language says this isn't called. */;
8181+
else if (!trivial)
81748182
{
81758183
if (!mark_used (fn, complain) && !(complain & tf_error))
81768184
return error_mark_node;
81778185
already_used = true;
81788186
}
8187+
else
8188+
cp_warn_deprecated_use (fn, complain);
81798189

81808190
/* If we're creating a temp and we already have one, don't create a
81818191
new one. If we're not creating a temp but we get one, use
81828192
INIT_EXPR to collapse the temp into our target. Otherwise, if the
81838193
ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
81848194
temp or an INIT_EXPR otherwise. */
8185-
fa = argarray[0];
81868195
if (is_dummy_object (fa))
81878196
{
81888197
if (TREE_CODE (arg) == TARGET_EXPR)
@@ -8191,7 +8200,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
81918200
return force_target_expr (DECL_CONTEXT (fn), arg, complain);
81928201
}
81938202
else if ((trivial || TREE_CODE (arg) == TARGET_EXPR)
8194-
&& !unsafe_copy_elision_p (fa, arg))
8203+
&& !unsafe)
81958204
{
81968205
tree to = cp_stabilize_reference (cp_build_fold_indirect_ref (fa));
81978206

@@ -8241,6 +8250,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
82418250
TREE_NO_WARNING (val) = 1;
82428251
}
82438252

8253+
cp_warn_deprecated_use (fn, complain);
8254+
82448255
return val;
82458256
}
82468257
else if (trivial_fn_p (fn))

gcc/cp/class.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5171,6 +5171,40 @@ classtype_has_move_assign_or_move_ctor_p (tree t, bool user_p)
51715171
return false;
51725172
}
51735173

5174+
/* If T, a class, has a user-provided copy constructor, copy assignment
5175+
operator, or destructor, returns that function. Otherwise, null. */
5176+
5177+
tree
5178+
classtype_has_user_copy_or_dtor (tree t)
5179+
{
5180+
if (!CLASSTYPE_LAZY_COPY_CTOR (t))
5181+
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
5182+
{
5183+
tree fn = *iter;
5184+
if (user_provided_p (fn) && copy_fn_p (fn))
5185+
return fn;
5186+
}
5187+
5188+
if (!CLASSTYPE_LAZY_COPY_ASSIGN (t))
5189+
for (ovl_iterator iter (get_class_binding_direct
5190+
(t, assign_op_identifier));
5191+
iter; ++iter)
5192+
{
5193+
tree fn = *iter;
5194+
if (user_provided_p (fn) && copy_fn_p (fn))
5195+
return fn;
5196+
}
5197+
5198+
if (!CLASSTYPE_LAZY_DESTRUCTOR (t))
5199+
{
5200+
tree fn = CLASSTYPE_DESTRUCTOR (t);
5201+
if (user_provided_p (fn))
5202+
return fn;
5203+
}
5204+
5205+
return NULL_TREE;
5206+
}
5207+
51745208
/* Nonzero if we need to build up a constructor call when initializing an
51755209
object of this class, either because it has a user-declared constructor
51765210
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)
52015235
{
52025236
tree fn = *iter;
52035237
if (!DECL_ARTIFICIAL (fn)
5238+
|| TREE_DEPRECATED (fn)
52045239
|| DECL_DELETED_FN (fn))
52055240
return true;
52065241
}
@@ -5228,6 +5263,7 @@ type_build_dtor_call (tree t)
52285263
{
52295264
tree fn = *iter;
52305265
if (!DECL_ARTIFICIAL (fn)
5266+
|| TREE_DEPRECATED (fn)
52315267
|| DECL_DELETED_FN (fn))
52325268
return true;
52335269
}

gcc/cp/cp-tree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6103,6 +6103,7 @@ extern bool is_std_init_list (tree);
61036103
extern bool is_list_ctor (tree);
61046104
extern void validate_conversion_obstack (void);
61056105
extern void mark_versions_used (tree);
6106+
extern bool cp_warn_deprecated_use (tree, tsubst_flags_t = tf_warning_or_error);
61066107
extern tree get_function_version_dispatcher (tree);
61076108

61086109
/* in class.c */
@@ -6164,6 +6165,7 @@ extern bool trivial_default_constructor_is_constexpr (tree);
61646165
extern bool type_has_constexpr_default_constructor (tree);
61656166
extern bool type_has_virtual_destructor (tree);
61666167
extern bool classtype_has_move_assign_or_move_ctor_p (tree, bool user_declared);
6168+
extern tree classtype_has_user_copy_or_dtor (tree);
61676169
extern bool type_build_ctor_call (tree);
61686170
extern bool type_build_dtor_call (tree);
61696171
extern void explain_non_literal_class (tree);
@@ -7157,7 +7159,6 @@ extern tree cxx_copy_lang_qualifiers (const_tree, const_tree);
71577159

71587160
extern void cxx_print_statistics (void);
71597161
extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);
7160-
extern void cp_warn_deprecated_use (tree);
71617162

71627163
/* in ptree.c */
71637164
extern void cxx_print_xnode (FILE *, tree, int);

gcc/cp/decl.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10388,18 +10388,12 @@ grokdeclarator (const cp_declarator *declarator,
1038810388
type = NULL_TREE;
1038910389
type_was_error_mark_node = true;
1039010390
}
10391-
/* If the entire declaration is itself tagged as deprecated then
10392-
suppress reports of deprecated items. */
10393-
if (type && TREE_DEPRECATED (type)
10394-
&& deprecated_state != DEPRECATED_SUPPRESS)
10395-
cp_warn_deprecated_use (type);
10391+
cp_warn_deprecated_use (type);
1039610392
if (type && TREE_CODE (type) == TYPE_DECL)
1039710393
{
1039810394
typedef_decl = type;
1039910395
type = TREE_TYPE (typedef_decl);
10400-
if (TREE_DEPRECATED (type)
10401-
&& DECL_ARTIFICIAL (typedef_decl)
10402-
&& deprecated_state != DEPRECATED_SUPPRESS)
10396+
if (DECL_ARTIFICIAL (typedef_decl))
1040310397
cp_warn_deprecated_use (type);
1040410398
}
1040510399
/* No type at all: default to `int', and set DEFAULTED_INT

gcc/cp/decl2.c

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5173,6 +5173,55 @@ maybe_instantiate_decl (tree decl)
51735173
}
51745174
}
51755175

5176+
/* Maybe warn if DECL is deprecated, subject to COMPLAIN. Returns whether or
5177+
not a warning was emitted. */
5178+
5179+
bool
5180+
cp_warn_deprecated_use (tree decl, tsubst_flags_t complain)
5181+
{
5182+
if (!(complain & tf_warning) || !decl
5183+
|| deprecated_state == DEPRECATED_SUPPRESS)
5184+
return false;
5185+
5186+
if (!TREE_DEPRECATED (decl))
5187+
{
5188+
/* Perhaps this is a deprecated typedef. */
5189+
if (TYPE_P (decl) && TYPE_NAME (decl))
5190+
decl = TYPE_NAME (decl);
5191+
5192+
if (!TREE_DEPRECATED (decl))
5193+
return false;
5194+
}
5195+
5196+
/* Don't warn within members of a deprecated type. */
5197+
if (TYPE_P (decl)
5198+
&& currently_open_class (decl))
5199+
return false;
5200+
5201+
bool warned = false;
5202+
if (cxx_dialect >= cxx11
5203+
&& DECL_P (decl)
5204+
&& DECL_ARTIFICIAL (decl)
5205+
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
5206+
&& copy_fn_p (decl))
5207+
{
5208+
warned = warning (OPT_Wdeprecated_copy,
5209+
"implicitly-declared %qD is deprecated", decl);
5210+
if (warned)
5211+
{
5212+
tree ctx = DECL_CONTEXT (decl);
5213+
tree other = classtype_has_user_copy_or_dtor (ctx);
5214+
inform (DECL_SOURCE_LOCATION (other),
5215+
"because %qT has user-provided %qD",
5216+
ctx, other);
5217+
}
5218+
}
5219+
else
5220+
warned = warn_deprecated_use (decl, NULL_TREE);
5221+
5222+
return warned;
5223+
}
5224+
51765225
/* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
51775226
If DECL is a specialization or implicitly declared class member,
51785227
generate the actual definition. Return false if something goes
@@ -5237,9 +5286,7 @@ mark_used (tree decl, tsubst_flags_t complain)
52375286
return false;
52385287
}
52395288

5240-
if (TREE_DEPRECATED (decl) && (complain & tf_warning)
5241-
&& deprecated_state != DEPRECATED_SUPPRESS)
5242-
warn_deprecated_use (decl, NULL_TREE);
5289+
cp_warn_deprecated_use (decl, complain);
52435290

52445291
/* We can only check DECL_ODR_USED on variables or functions with
52455292
DECL_LANG_SPECIFIC set, and these are also the only decls that we

gcc/cp/init.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,11 +1733,6 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
17331733
&& !DIRECT_LIST_INIT_P (init))
17341734
flags |= LOOKUP_ONLYCONVERTING;
17351735

1736-
if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
1737-
&& !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
1738-
/* Just know that we've seen something for this node. */
1739-
TREE_USED (exp) = 1;
1740-
17411736
is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
17421737
destroy_temps = stmts_are_full_exprs_p ();
17431738
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)
17481743
TREE_READONLY (exp) = was_const;
17491744
TREE_THIS_VOLATILE (exp) = was_volatile;
17501745

1746+
if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
1747+
&& TREE_SIDE_EFFECTS (stmt_expr)
1748+
&& !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
1749+
/* Just know that we've seen something for this node. */
1750+
TREE_USED (exp) = 1;
1751+
17511752
return stmt_expr;
17521753
}
17531754

gcc/cp/method.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,8 +2394,19 @@ lazily_declare_fn (special_function_kind sfk, tree type)
23942394
move assignment operator, the implicitly declared copy constructor is
23952395
defined as deleted.... */
23962396
if ((sfk == sfk_copy_assignment || sfk == sfk_copy_constructor)
2397-
&& classtype_has_move_assign_or_move_ctor_p (type, true))
2398-
DECL_DELETED_FN (fn) = true;
2397+
&& cxx_dialect >= cxx11)
2398+
{
2399+
if (classtype_has_move_assign_or_move_ctor_p (type, true))
2400+
DECL_DELETED_FN (fn) = true;
2401+
else if (classtype_has_user_copy_or_dtor (type))
2402+
/* The implicit definition of a copy constructor as defaulted is
2403+
deprecated if the class has a user-declared copy assignment operator
2404+
or a user-declared destructor. The implicit definition of a copy
2405+
assignment operator as defaulted is deprecated if the class has a
2406+
user-declared copy constructor or a user-declared destructor (15.4,
2407+
15.8). */
2408+
TREE_DEPRECATED (fn) = true;
2409+
}
23992410

24002411
/* Destructors and assignment operators may be virtual. */
24012412
if (sfk == sfk_destructor

gcc/cp/tree.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,19 +5398,6 @@ cp_tree_code_length (enum tree_code code)
53985398
}
53995399
}
54005400

5401-
/* Wrapper around warn_deprecated_use that doesn't warn for
5402-
current_class_type. */
5403-
5404-
void
5405-
cp_warn_deprecated_use (tree node)
5406-
{
5407-
if (TYPE_P (node)
5408-
&& current_class_type
5409-
&& TYPE_MAIN_VARIANT (node) == current_class_type)
5410-
return;
5411-
warn_deprecated_use (node, NULL_TREE);
5412-
}
5413-
54145401
/* Implement -Wzero_as_null_pointer_constant. Return true if the
54155402
conditions for the warning hold, false otherwise. */
54165403
bool

gcc/cp/typeck2.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,9 +2064,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
20642064
{
20652065
type = TREE_TYPE (exp);
20662066

2067-
if (complain & tf_warning
2068-
&& TREE_DEPRECATED (type)
2069-
&& DECL_ARTIFICIAL (exp))
2067+
if (DECL_ARTIFICIAL (exp))
20702068
cp_warn_deprecated_use (type);
20712069
}
20722070
else

gcc/doc/invoke.texi

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ in the following sections.
213213
-fvisibility-ms-compat @gol
214214
-fext-numeric-literals @gol
215215
-Wabi=@var{n} -Wabi-tag -Wconversion-null -Wctor-dtor-privacy @gol
216-
-Wdelete-non-virtual-dtor -Wliteral-suffix -Wmultiple-inheritance @gol
216+
-Wdelete-non-virtual-dtor -Wdeprecated-copy -Wliteral-suffix @gol
217+
-Wmultiple-inheritance @gol
217218
-Wnamespaces -Wnarrowing @gol
218219
-Wnoexcept -Wnoexcept-type -Wclass-memaccess @gol
219220
-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
29002901
base class does not have a virtual destructor. This warning is enabled
29012902
by @option{-Wall}.
29022903

2904+
@item -Wdeprecated-copy @r{(C++ and Objective-C++ only)}
2905+
@opindex Wdeprecated-copy
2906+
@opindex Wno-deprecated-copy
2907+
Warn that the implicit declaration of a copy constructor or copy
2908+
assignment operator is deprecated if the class has a user-provided
2909+
copy constructor, copy assignment operator, or destructor, in C++11
2910+
and up. This warning is enabled by @option{-Wall}.
2911+
29032912
@item -Wliteral-suffix @r{(C++ and Objective-C++ only)}
29042913
@opindex Wliteral-suffix
29052914
@opindex Wno-literal-suffix
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* [depr.impldec] The implicit definition of a copy constructor as defaulted is
2+
deprecated if the class has a user-declared copy assignment operator or a
3+
user-declared destructor. The implicit definition of a copy assignment
4+
operator as defaulted is deprecated if the class has a user-declared copy
5+
constructor or a user-declared destructor (15.4, 15.8). In a future revision
6+
of this International Standard, these implicit definitions could become
7+
deleted (11.4). */
8+
9+
// { dg-additional-options -Wdeprecated-copy }
10+
11+
struct X
12+
{
13+
X();
14+
X(const X&);
15+
};
16+
struct A
17+
{
18+
X x;
19+
~A();
20+
};
21+
22+
void f(bool b)
23+
{
24+
A a;
25+
if (b)
26+
throw A(); // Don't warn about elided copy
27+
A a2 = A(); // Here either.
28+
A a3 (a); // { dg-warning "deprecated" "" { target c++11 } }
29+
}

0 commit comments

Comments
 (0)