aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2012-07-11 07:53:23 -0400
committerJason Merrill <jason@gcc.gnu.org>2012-07-11 07:53:23 -0400
commit45ffb6f7436e7f2cebc61a18108bad5b38cc4fd4 (patch)
treea8706d18216573732634c99a664840765d92409b /gcc
parent6bdf3519449086bc04f2431305607ff8c71e27ca (diff)
downloadgcc-45ffb6f7436e7f2cebc61a18108bad5b38cc4fd4.zip
gcc-45ffb6f7436e7f2cebc61a18108bad5b38cc4fd4.tar.gz
gcc-45ffb6f7436e7f2cebc61a18108bad5b38cc4fd4.tar.bz2
DR 1402
DR 1402 * method.c (synthesized_method_walk): Replace uses of msg with diag. Correct handling of virtual bases with move operations. (process_subob_fn, walk_field_subobs): Replace uses of msg with diag. From-SVN: r189426
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/method.c91
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted37.C21
4 files changed, 78 insertions, 46 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a59cefe..fd2ba73 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2012-07-11 Jason Merrill <jason@redhat.com>
+
+ DR 1402
+ * method.c (synthesized_method_walk): Replace uses of msg with diag.
+ Correct handling of virtual bases with move operations.
+ (process_subob_fn, walk_field_subobs): Replace uses of msg with diag.
+
2012-07-11 Steven Bosscher <steven@gcc.gnu.org>
* method.c: Do not include tree-pass.h.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 9481aa7..bd0792f 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 *no_implicit_p,
- const char *msg, tree arg)
+ bool diag, tree arg)
{
if (!fn || fn == error_mark_node)
goto bad;
@@ -942,7 +942,7 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
{
if (deleted_p)
*deleted_p = true;
- if (msg)
+ if (diag)
error ("union member %q+D with non-trivial %qD", arg, fn);
}
}
@@ -955,7 +955,7 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn))
{
*constexpr_p = false;
- if (msg)
+ if (diag)
{
inform (0, "defaulted constructor calls non-constexpr "
"%q+D", fn);
@@ -978,7 +978,7 @@ 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, bool *no_implicit_p,
- const char *msg, int flags, tsubst_flags_t complain)
+ bool diag, int flags, tsubst_flags_t complain)
{
tree field;
for (field = fields; field; field = DECL_CHAIN (field))
@@ -995,13 +995,13 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
bool bad = true;
if (CP_TYPE_CONST_P (mem_type) && !CLASS_TYPE_P (mem_type))
{
- if (msg)
+ if (diag)
error ("non-static const member %q#D, can%'t use default "
"assignment operator", field);
}
else if (TREE_CODE (mem_type) == REFERENCE_TYPE)
{
- if (msg)
+ if (diag)
error ("non-static reference member %q#D, can%'t use "
"default assignment operator", field);
}
@@ -1017,7 +1017,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
if (DECL_INITIAL (field))
{
- if (msg && DECL_INITIAL (field) == error_mark_node)
+ if (diag && DECL_INITIAL (field) == error_mark_node)
inform (0, "initializer for %q+#D is invalid", field);
if (trivial_p)
*trivial_p = false;
@@ -1040,14 +1040,14 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
if (CP_TYPE_CONST_P (mem_type)
&& default_init_uninitialized_part (mem_type))
{
- if (msg)
+ if (diag)
error ("uninitialized non-static const member %q#D",
field);
bad = true;
}
else if (TREE_CODE (mem_type) == REFERENCE_TYPE)
{
- if (msg)
+ if (diag)
error ("uninitialized non-static reference member %q#D",
field);
bad = true;
@@ -1063,7 +1063,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
&& TREE_CODE (DECL_CONTEXT (field)) != UNION_TYPE)
{
*constexpr_p = false;
- if (msg)
+ if (diag)
inform (0, "defaulted default constructor does not "
"initialize %q+#D", field);
}
@@ -1077,7 +1077,7 @@ 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, no_implicit_p,
- msg, flags, complain);
+ diag, flags, complain);
continue;
}
@@ -1094,7 +1094,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, no_implicit_p, msg, field);
+ constexpr_p, no_implicit_p, diag, field);
}
}
@@ -1115,7 +1115,6 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
VEC(tree,gc) *vbases;
int i, quals, flags;
tsubst_flags_t complain;
- const char *msg;
bool ctor_p;
if (spec_p)
@@ -1239,25 +1238,21 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
quals = TYPE_UNQUALIFIED;
argtype = NULL_TREE;
- if (!diag)
- msg = NULL;
- else if (assign_p)
- msg = ("base %qT does not have a move assignment operator or trivial "
- "copy assignment operator");
- else
- msg = ("base %qT does not have a move constructor or trivial "
- "copy constructor");
-
for (binfo = TYPE_BINFO (ctype), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
tree basetype = BINFO_TYPE (base_binfo);
+
+ if (!assign_p && BINFO_VIRTUAL_P (base_binfo))
+ /* We'll handle virtual bases below. */
+ continue;
+
if (copy_arg_p)
argtype = build_stub_type (basetype, quals, move_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, no_implicit_p, msg, basetype);
+ constexpr_p, no_implicit_p, diag, basetype);
if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
{
/* In a constructor we also need to check the subobject
@@ -1270,7 +1265,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, NULL,
+ deleted_p, NULL, NULL, false,
basetype);
}
@@ -1287,21 +1282,31 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
}
vbases = CLASSTYPE_VBASECLASSES (ctype);
- if (vbases && assign_p && move_p)
+ if (vbases == NULL)
+ /* No virtual bases to worry about. */;
+ else if (assign_p && move_p && no_implicit_p)
{
+ /* Don't implicitly declare a defaulted move assignment if a virtual
+ base has non-trivial move assignment, since moving the same base
+ more than once is dangerous. */
/* Should the spec be changed to allow vbases that only occur once? */
- if (diag)
- error ("%qT has virtual bases, default move assignment operator "
- "cannot be generated", ctype);
- else if (deleted_p)
- *deleted_p = true;
+ FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo)
+ {
+ tree basetype = BINFO_TYPE (base_binfo);
+ if (copy_arg_p)
+ argtype = build_stub_type (basetype, quals, move_p);
+ rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
+ if (rval && rval != error_mark_node
+ && move_fn_p (rval) && !trivial_fn_p (rval))
+ {
+ *no_implicit_p = true;
+ break;
+ }
+ }
}
else if (!assign_p)
{
- if (diag)
- msg = ("virtual base %qT does not have a move constructor "
- "or trivial copy constructor");
- if (vbases && constexpr_p)
+ if (constexpr_p)
*constexpr_p = false;
FOR_EACH_VEC_ELT (tree, vbases, i, base_binfo)
{
@@ -1311,35 +1316,29 @@ 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, no_implicit_p, msg, basetype);
+ constexpr_p, no_implicit_p, diag, 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, NULL,
+ deleted_p, NULL, NULL, false,
basetype);
}
}
}
- if (!diag)
- /* Leave msg null. */;
- else if (assign_p)
- msg = ("non-static data member %qD does not have a move "
- "assignment operator or trivial copy assignment operator");
- else
- msg = ("non-static data member %qD does not have a move "
- "constructor or trivial copy constructor");
+
+ /* Now handle the non-static data members. */
walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals,
copy_arg_p, move_p, assign_p, spec_p, trivial_p,
deleted_p, constexpr_p, no_implicit_p,
- msg, flags, complain);
+ diag, 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, NULL, flags, complain);
+ NULL, false, flags, complain);
pop_scope (scope);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cd9d0a8..a82ac1c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-11 Jason Merrill <jason@redhat.com>
+
+ DR 1402
+ * g++.g/cpp0x/defaulted37.C: New.
+
2012-07-11 Greta Yorsh <Greta.Yorsh@arm.com>
PR target/53859
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted37.C b/gcc/testsuite/g++.dg/cpp0x/defaulted37.C
new file mode 100644
index 0000000..69105cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted37.C
@@ -0,0 +1,21 @@
+// DR 1402
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ int moved = 0;
+ A& operator=(A&&) { ++moved; }
+ ~A() { if (moved > 1) __builtin_abort(); }
+};
+
+struct B: virtual A { B& operator=(B&&) = default; };
+struct C: virtual A { }; // { dg-error "operator=.const A&" }
+
+int main()
+{
+ B b1, b2;
+ b2 = static_cast<B&&>(b1);
+
+ C c1, c2;
+ c2 = static_cast<C&&>(c1); // { dg-error "operator=.const C&" }
+}