From a57df396bd4b901a12316397d21fb928f27eee84 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 10 Jul 2012 00:03:23 +0000 Subject: [PATCH] DR 1402 PR c++/53733 * cp-tree.h (FNDECL_SUPPRESS_IMPLICIT_DECL): New. (struct lang_decl_fn): Add suppress_implicit_decl field. * method.c (implicitly_declare_fn): Check it. (process_subob_fn): Add no_implicit_p parm. (walk_field_subobs, synthesized_method_walk): Likewise. (maybe_explain_implicit_delete): Adjust. (explain_implicit_non_constexpr): Adjust. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189396 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 10 +++++++ gcc/cp/cp-tree.h | 8 +++++- gcc/cp/method.c | 49 +++++++++++++++++++------------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/g++.dg/cpp0x/defaulted21.C | 5 ++-- gcc/testsuite/g++.dg/cpp0x/defaulted36.C | 24 ++++++++++++++++ 6 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/defaulted36.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e4c5506986c..310b44259b9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 2012-07-10 Jason Merrill + DR 1402 + PR c++/53733 + * cp-tree.h (FNDECL_SUPPRESS_IMPLICIT_DECL): New. + (struct lang_decl_fn): Add suppress_implicit_decl field. + * method.c (implicitly_declare_fn): Check it. + (process_subob_fn): Add no_implicit_p parm. + (walk_field_subobs, synthesized_method_walk): Likewise. + (maybe_explain_implicit_delete): Adjust. + (explain_implicit_non_constexpr): Adjust. + * method.c (synthesized_method_walk): Avoid changing EH spec based on cleanups in other places, too. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 713001e121f..10efa2a663a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1940,7 +1940,7 @@ struct GTY(()) lang_decl_fn { unsigned thunk_p : 1; unsigned this_thunk_p : 1; unsigned hidden_friend_p : 1; - /* 1 spare bit. */ + unsigned suppress_implicit_decl : 1; /* For a non-thunk function decl, this is a tree list of friendly classes. For a thunk function decl, it is the @@ -3107,6 +3107,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define DECL_HIDDEN_FRIEND_P(NODE) \ (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->hidden_friend_p) +/* Nonzero if NODE is a FUNCTION_DECL generated by implicitly_declare_fn + that we shouldn't actually declare implicitly; it is only used for + comparing to an =default declaration. */ +#define FNDECL_SUPPRESS_IMPLICIT_DECL(NODE) \ + (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->suppress_implicit_decl) + /* Nonzero if DECL has been declared threadprivate by #pragma omp threadprivate. */ #define CP_DECL_THREADPRIVATE_P(DECL) \ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 7ea2de9ac8e..79edf81b24f 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -922,7 +922,7 @@ get_copy_assign (tree type) static void process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p, - bool *deleted_p, bool *constexpr_p, + bool *deleted_p, bool *constexpr_p, bool *no_implicit_p, const char *msg, tree arg) { if (!fn || fn == error_mark_node) @@ -948,12 +948,10 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p, } } + /* Core 1402: A non-trivial copy op suppresses the implicit + declaration of the move ctor/op=. */ if (move_p && !move_fn_p (fn) && !trivial_fn_p (fn)) - { - if (msg) - error (msg, arg); - goto bad; - } + *no_implicit_p = true; if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn)) { @@ -980,8 +978,8 @@ static void walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, int quals, bool copy_arg_p, bool move_p, bool assign_p, tree *spec_p, bool *trivial_p, - bool *deleted_p, bool *constexpr_p, const char *msg, - int flags, tsubst_flags_t complain) + bool *deleted_p, bool *constexpr_p, bool *no_implicit_p, + const char *msg, int flags, tsubst_flags_t complain) { tree field; for (field = fields; field; field = DECL_CHAIN (field)) @@ -1079,7 +1077,8 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, { walk_field_subobs (TYPE_FIELDS (mem_type), fnname, sfk, quals, copy_arg_p, move_p, assign_p, spec_p, trivial_p, - deleted_p, constexpr_p, msg, flags, complain); + deleted_p, constexpr_p, no_implicit_p, + msg, flags, complain); continue; } @@ -1096,7 +1095,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain); process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, - constexpr_p, msg, field); + constexpr_p, no_implicit_p, msg, field); } } @@ -1110,7 +1109,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, static void synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, tree *spec_p, bool *trivial_p, bool *deleted_p, - bool *constexpr_p, bool diag) + bool *constexpr_p, bool *no_implicit_p, bool diag) { tree binfo, base_binfo, scope, fnname, rval, argtype; bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor; @@ -1198,6 +1197,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, if (trivial_p) *trivial_p = expected_trivial; + if (no_implicit_p) + *no_implicit_p = false; + /* The TYPE_HAS_COMPLEX_* flags tell us about constraints from base class versions and other properties of the type. But a subobject class can be trivially copyable and yet have overload resolution @@ -1256,7 +1258,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, - constexpr_p, msg, basetype); + constexpr_p, no_implicit_p, msg, basetype); if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype)) { /* In a constructor we also need to check the subobject @@ -1269,7 +1271,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, throw) or exception-specification (a throw from one of the dtors would be a double-fault). */ process_subob_fn (rval, false, NULL, NULL, - deleted_p, NULL, NULL, + deleted_p, NULL, NULL, NULL, basetype); } @@ -1310,13 +1312,13 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, - constexpr_p, msg, basetype); + constexpr_p, no_implicit_p, msg, basetype); if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype)) { rval = locate_fn_flags (base_binfo, complete_dtor_identifier, NULL_TREE, flags, complain); process_subob_fn (rval, false, NULL, NULL, - deleted_p, NULL, NULL, + deleted_p, NULL, NULL, NULL, basetype); } } @@ -1331,13 +1333,14 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, "constructor or trivial copy constructor"); walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals, copy_arg_p, move_p, assign_p, spec_p, trivial_p, - deleted_p, constexpr_p, msg, flags, complain); + deleted_p, constexpr_p, no_implicit_p, + msg, flags, complain); if (ctor_p) walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier, sfk_destructor, TYPE_UNQUALIFIED, false, false, false, NULL, NULL, deleted_p, NULL, - NULL, flags, complain); + NULL, NULL, flags, complain); pop_scope (scope); @@ -1407,7 +1410,7 @@ maybe_explain_implicit_delete (tree decl) "definition would be ill-formed:", decl); pop_scope (scope); synthesized_method_walk (ctype, sfk, const_p, - NULL, NULL, NULL, NULL, true); + NULL, NULL, NULL, NULL, NULL, true); } input_location = loc; @@ -1427,7 +1430,7 @@ explain_implicit_non_constexpr (tree decl) bool dummy; synthesized_method_walk (DECL_CLASS_CONTEXT (decl), special_function_p (decl), const_p, - NULL, NULL, NULL, &dummy, true); + NULL, NULL, NULL, &dummy, NULL, true); } /* Implicitly declare the special function indicated by KIND, as a @@ -1451,6 +1454,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) bool deleted_p; bool trivial_p; bool constexpr_p; + bool no_implicit_p; /* Because we create declarations for implicitly declared functions lazily, we may be creating the declaration for a member of TYPE @@ -1520,7 +1524,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) } synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, - &deleted_p, &constexpr_p, false); + &deleted_p, &constexpr_p, &no_implicit_p, false); /* Don't bother marking a deleted constructor as constexpr. */ if (deleted_p) constexpr_p = false; @@ -1585,6 +1589,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) DECL_DELETED_FN (fn) = deleted_p; DECL_DECLARED_CONSTEXPR_P (fn) = constexpr_p; } + FNDECL_SUPPRESS_IMPLICIT_DECL (fn) = no_implicit_p; DECL_EXTERNAL (fn) = true; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; @@ -1777,6 +1782,10 @@ lazily_declare_fn (special_function_kind sfk, tree type) || sfk == sfk_move_assignment)) return NULL_TREE; + /* We also suppress implicit move if it would call a non-trivial copy. */ + if (FNDECL_SUPPRESS_IMPLICIT_DECL (fn)) + return NULL_TREE; + /* A destructor may be virtual. */ if (sfk == sfk_destructor || sfk == sfk_move_assignment diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 41e3c64ead9..9787afecf44 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2012-07-10 Jason Merrill + PR c++/53733 + * g++.dg/cpp0x/defaulted36.C: New. + * g++.dg/cpp0x/defaulted21.C: Adjust. + * g++.dg/cpp0x/implicit13.C: Add vbase and member tests. 2012-07-09 Sterling Augustine diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C index 30a4a7c7d01..51505dc460e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C @@ -3,7 +3,8 @@ struct U { U(); - U(U const&); +private: + U(U const&); // { dg-error "private" } }; struct X { @@ -13,7 +14,7 @@ struct X { }; X::X(X&&)=default; // { dg-message "implicitly deleted" } -// { dg-error "does not have a move constructor" "" { target *-*-* } 15 } +// { dg-prune-output "within this context" } X f() { return X(); diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted36.C b/gcc/testsuite/g++.dg/cpp0x/defaulted36.C new file mode 100644 index 00000000000..1360f608e69 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted36.C @@ -0,0 +1,24 @@ +// PR c++/53733 +// { dg-do compile { target c++11 } } + +template +struct wrap +{ + wrap() = default; + wrap(wrap&&) = default; // Line 5 + wrap(const wrap&) = default; + + T t; +}; + +struct S { + S() = default; + S(const S&){} + S(S&&) = default; +}; + +typedef wrap W; + +W get() { return W(); } // Line 19 + +int main() {} -- 2.11.4.GIT