Patchwork C++ PATCH for c++/50500 (DR 1082, implicitly declared copy in class with move)

login
register
mail settings
Submitter Jason Merrill
Date Nov. 1, 2011, 1:41 p.m.
Message ID <4EAFF6FD.3000402@redhat.com>
Download mbox | patch
Permalink /patch/123071/
State New
Headers show

Comments

Jason Merrill - Nov. 1, 2011, 1:41 p.m.
On 10/29/2011 05:07 PM, Eric Botcazou wrote:
>> DR 1082 changed the rules for implicitly declared copy constructors and
>> assignment operators in the presence of move ctor/op= such that if
>> either move operation is present, instead of being suppressed the copy
>> operations will still be declared, but as deleted.
>
> We have detected a side effect of this change by means of -fdump-ada-spec:
> implicit copy assignment operators are now generated in simple cases where
> they were not previously generated, for example:

Oops, thanks.  Fixed thus.

Patch

commit 06151eabf195163c8885da36abae67ab60cf1978
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Oct 31 16:57:17 2011 -0400

    	PR c++/50500
    	DR 1082
    	* search.c (lookup_fnfields_idx_nolazy): Split out from...
    	(lookup_fnfields_1): ...here.
    	(lookup_fnfields_slot_nolazy): Use it.
    	* cp-tree.h: Declare it.
    	* class.c (type_has_move_assign): Use it.
    	(type_has_user_declared_move_assign): Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a014d25..41d182a 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4485,7 +4485,7 @@  type_has_move_assign (tree t)
       lazily_declare_fn (sfk_move_assignment, t);
     }
 
-  for (fns = lookup_fnfields_slot (t, ansi_assopname (NOP_EXPR));
+  for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
        fns; fns = OVL_NEXT (fns))
     if (move_fn_p (OVL_CURRENT (fns)))
       return true;
@@ -4530,7 +4530,7 @@  type_has_user_declared_move_assign (tree t)
   if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
     return false;
 
-  for (fns = lookup_fnfields_slot (t, ansi_assopname (NOP_EXPR));
+  for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
        fns; fns = OVL_NEXT (fns))
     {
       tree fn = OVL_CURRENT (fns);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7ff1491..ac42e0e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5328,6 +5328,7 @@  extern tree lookup_field_1			(tree, tree, bool);
 extern tree lookup_field			(tree, tree, int, bool);
 extern int lookup_fnfields_1			(tree, tree);
 extern tree lookup_fnfields_slot		(tree, tree);
+extern tree lookup_fnfields_slot_nolazy		(tree, tree);
 extern int class_method_index_for_fn		(tree, tree);
 extern tree lookup_fnfields			(tree, tree, int);
 extern tree lookup_member			(tree, tree, int, bool);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 97f593c..5f60eee 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1335,10 +1335,11 @@  lookup_conversion_operator (tree class_type, tree type)
 }
 
 /* TYPE is a class type. Return the index of the fields within
-   the method vector with name NAME, or -1 if no such field exists.  */
+   the method vector with name NAME, or -1 if no such field exists.
+   Does not lazily declare implicitly-declared member functions.  */
 
-int
-lookup_fnfields_1 (tree type, tree name)
+static int
+lookup_fnfields_idx_nolazy (tree type, tree name)
 {
   VEC(tree,gc) *method_vec;
   tree fn;
@@ -1348,34 +1349,6 @@  lookup_fnfields_1 (tree type, tree name)
   if (!CLASS_TYPE_P (type))
     return -1;
 
-  if (COMPLETE_TYPE_P (type))
-    {
-      if ((name == ctor_identifier
-	   || name == base_ctor_identifier
-	   || name == complete_ctor_identifier))
-	{
-	  if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
-	    lazily_declare_fn (sfk_constructor, type);
-	  if (CLASSTYPE_LAZY_COPY_CTOR (type))
-	    lazily_declare_fn (sfk_copy_constructor, type);
-	  if (CLASSTYPE_LAZY_MOVE_CTOR (type))
-	    lazily_declare_fn (sfk_move_constructor, type);
-	}
-      else if (name == ansi_assopname (NOP_EXPR))
-	{
-	  if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
-	    lazily_declare_fn (sfk_copy_assignment, type);
-	  if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
-	    lazily_declare_fn (sfk_move_assignment, type);
-	}
-      else if ((name == dtor_identifier
-		|| name == base_dtor_identifier
-		|| name == complete_dtor_identifier
-		|| name == deleting_dtor_identifier)
-	       && CLASSTYPE_LAZY_DESTRUCTOR (type))
-	lazily_declare_fn (sfk_destructor, type);
-    }
-
   method_vec = CLASSTYPE_METHOD_VEC (type);
   if (!method_vec)
     return -1;
@@ -1445,6 +1418,46 @@  lookup_fnfields_1 (tree type, tree name)
   return -1;
 }
 
+/* TYPE is a class type. Return the index of the fields within
+   the method vector with name NAME, or -1 if no such field exists.  */
+
+int
+lookup_fnfields_1 (tree type, tree name)
+{
+  if (!CLASS_TYPE_P (type))
+    return -1;
+
+  if (COMPLETE_TYPE_P (type))
+    {
+      if ((name == ctor_identifier
+	   || name == base_ctor_identifier
+	   || name == complete_ctor_identifier))
+	{
+	  if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+	    lazily_declare_fn (sfk_constructor, type);
+	  if (CLASSTYPE_LAZY_COPY_CTOR (type))
+	    lazily_declare_fn (sfk_copy_constructor, type);
+	  if (CLASSTYPE_LAZY_MOVE_CTOR (type))
+	    lazily_declare_fn (sfk_move_constructor, type);
+	}
+      else if (name == ansi_assopname (NOP_EXPR))
+	{
+	  if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
+	    lazily_declare_fn (sfk_copy_assignment, type);
+	  if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
+	    lazily_declare_fn (sfk_move_assignment, type);
+	}
+      else if ((name == dtor_identifier
+		|| name == base_dtor_identifier
+		|| name == complete_dtor_identifier
+		|| name == deleting_dtor_identifier)
+	       && CLASSTYPE_LAZY_DESTRUCTOR (type))
+	lazily_declare_fn (sfk_destructor, type);
+    }
+
+  return lookup_fnfields_idx_nolazy (type, name);
+}
+
 /* TYPE is a class type. Return the field within the method vector with
    name NAME, or NULL_TREE if no such field exists.  */
 
@@ -1457,6 +1470,17 @@  lookup_fnfields_slot (tree type, tree name)
   return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
 }
 
+/* As above, but avoid lazily declaring functions.  */
+
+tree
+lookup_fnfields_slot_nolazy (tree type, tree name)
+{
+  int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
+  if (ix < 0)
+    return NULL_TREE;
+  return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+}
+
 /* Like lookup_fnfields_1, except that the name is extracted from
    FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL.  */