diff mbox

C++ PATCH for c++/46736 (missing diagnostic for invalid =default)

Message ID 4CFFE382.4010002@redhat.com
State New
Headers show

Commit Message

Jason Merrill Dec. 8, 2010, 7:58 p.m. UTC
When a special member function which would be implicitly deleted is 
defaulted outside the class, we need to give a diagnostic at that point.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit d63174fad262075f58348e3240445bd384caf309
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Dec 4 01:28:18 2010 -0500

    	PR c++/45822
    	* cp-tree.h (LOOKUP_DEFAULTED): New.
    	* call.c (add_function_candidate): Check it.
    	* method.c (synthesized_method_walk): Set it.
    	(do_build_copy_assign): Likewise.
    	* init.c (perform_member_init): Likewise.
    	(emit_mem_initializers): Likewise.

Comments

Dodji Seketeli Dec. 9, 2010, 1:42 p.m. UTC | #1
Jason Merrill <jason@redhat.com> writes:

> When a special member function which would be implicitly deleted is
> defaulted outside the class, we need to give a diagnostic at that
> point.
>
> Tested x86_64-pc-linux-gnu, applied to trunk.
>
> commit d63174fad262075f58348e3240445bd384caf309
> Author: Jason Merrill <jason@redhat.com>
> Date:   Sat Dec 4 01:28:18 2010 -0500
>
>     	PR c++/45822
>     	* cp-tree.h (LOOKUP_DEFAULTED): New.
>     	* call.c (add_function_candidate): Check it.
>     	* method.c (synthesized_method_walk): Set it.
>     	(do_build_copy_assign): Likewise.
>     	* init.c (perform_member_init): Likewise.
>     	(emit_mem_initializers): Likewise.
>

Not very important but it looks like this patch does not correspond to
the subject.
diff mbox

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4929d4f..16a369a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1645,13 +1645,10 @@  add_function_candidate (struct z_candidate **candidates,
   else if (!sufficient_parms_p (parmnode))
     viable = 0;
 
-  /* Kludge: When looking for a function from a subobject while generating
-     an implicit copy/move constructor/operator=, don't consider anything
-     that takes (a reference to) an unrelated type.  See c++/44909.  */
-  else if (parmlist
-	   && ((flags & LOOKUP_SPECULATIVE)
-	       || (current_function_decl
-		   && DECL_DEFAULTED_FN (current_function_decl))))
+  /* When looking for a function from a subobject from an implicit
+     copy/move constructor/operator=, don't consider anything that takes (a
+     reference to) an unrelated type.  See c++/44909 and core 1092.  */
+  else if (parmlist && (flags & LOOKUP_DEFAULTED))
     {
       if (DECL_CONSTRUCTOR_P (fn))
 	i = 1;
@@ -1667,6 +1664,9 @@  add_function_candidate (struct z_candidate **candidates,
 				    ctype))
 	    viable = 0;
 	}
+
+      /* This only applies at the top level.  */
+      flags &= ~LOOKUP_DEFAULTED;
     }
 
   if (! viable)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index aba8dfd..03c02fc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4227,9 +4227,12 @@  enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
    another mechanism.  Exiting early also avoids problems with trying
    to perform argument conversions when the class isn't complete yet.  */
 #define LOOKUP_SPECULATIVE (LOOKUP_LIST_ONLY << 1)
+/* Used by calls from defaulted functions to limit the overload set to avoid
+   cycles trying to declare them (core issue 1092).  */
+#define LOOKUP_DEFAULTED (LOOKUP_SPECULATIVE << 1)
 /* Used in calls to store_init_value to suppress its usual call to
    digest_init.  */
-#define LOOKUP_ALREADY_DIGESTED (LOOKUP_SPECULATIVE << 1)
+#define LOOKUP_ALREADY_DIGESTED (LOOKUP_DEFAULTED << 1)
 
 #define LOOKUP_NAMESPACES_ONLY(F)  \
   (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 9de8c9f..5a4f91c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -503,6 +503,9 @@  perform_member_init (tree member, tree init)
 	}
       else
 	{
+	  int flags = LOOKUP_NORMAL;
+	  if (DECL_DEFAULTED_FN (current_function_decl))
+	    flags |= LOOKUP_DEFAULTED;
 	  if (CP_TYPE_CONST_P (type)
 	      && init == NULL_TREE
 	      && !type_has_user_provided_default_constructor (type))
@@ -511,7 +514,7 @@  perform_member_init (tree member, tree init)
 	    permerror (DECL_SOURCE_LOCATION (current_function_decl),
 		       "uninitialized member %qD with %<const%> type %qT",
 		       member, type);
-	  finish_expr_stmt (build_aggr_init (decl, init, 0, 
+	  finish_expr_stmt (build_aggr_init (decl, init, flags,
 					     tf_warning_or_error));
 	}
     }
@@ -852,11 +855,16 @@  sort_mem_initializers (tree t, tree mem_inits)
 void
 emit_mem_initializers (tree mem_inits)
 {
+  int flags = LOOKUP_NORMAL;
+
   /* We will already have issued an error message about the fact that
      the type is incomplete.  */
   if (!COMPLETE_TYPE_P (current_class_type))
     return;
 
+  if (DECL_DEFAULTED_FN (current_function_decl))
+    flags |= LOOKUP_DEFAULTED;
+
   /* Sort the mem-initializers into the order in which the
      initializations should be performed.  */
   mem_inits = sort_mem_initializers (current_class_type, mem_inits);
@@ -908,7 +916,7 @@  emit_mem_initializers (tree mem_inits)
 			      cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
 			      arguments,
-			      LOOKUP_NORMAL,
+			      flags,
                               tf_warning_or_error);
 	  expand_cleanup_for_base (subobject, NULL_TREE);
 	}
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index dc72355..149910c 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -583,6 +583,7 @@  do_build_copy_assign (tree fndecl)
   tree compound_stmt;
   bool move_p = move_fn_p (fndecl);
   bool trivial = trivial_fn_p (fndecl);
+  int flags = LOOKUP_NORMAL | LOOKUP_NONVIRTUAL | LOOKUP_DEFAULTED;
 
   compound_stmt = begin_compound_stmt (0);
   parm = convert_from_reference (parm);
@@ -622,7 +623,7 @@  do_build_copy_assign (tree fndecl)
 					ansi_assopname (NOP_EXPR),
 					&parmvec,
 					base_binfo,
-					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
+					flags,
                                         tf_warning_or_error));
 	  release_tree_vector (parmvec);
 	}
@@ -1175,12 +1176,12 @@  synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
 
   if (diag)
     {
-      flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE;
+      flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED;
       complain = tf_warning_or_error;
     }
   else
     {
-      flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE;
+      flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED;
       complain = tf_none;
     }
 
diff --git a/gcc/testsuite/g++.dg/init/synth4.C b/gcc/testsuite/g++.dg/init/synth4.C
new file mode 100644
index 0000000..2b0b0b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/synth4.C
@@ -0,0 +1,18 @@ 
+// PR c++/45822
+
+struct A
+{
+  A(int);
+};
+
+struct B
+{
+  B(A = 0);
+};
+
+struct C
+{
+  B b;
+};
+
+C c;