On 06/12/2017 03:36 PM, Jason Merrill wrote:
On 06/08/2017 01:25 PM, Martin Sebor wrote:
+      if (TREE_CHAIN (DECL_ARGUMENTS (f)))
+    {
+      /* Skip constructors that aren't copy or move ctors.  */
+      if (!copy_fn_p (f))
+        continue;
+
+      cpy_or_move_ctor_p = true;
+    }
+      else
+    {
+      /* Constructor is a default ctor.  */
+      cpy_or_move_ctor_p = false;
+    }

A default constructor can have parameters, so long as they have default
arguments.  You can use default_ctor_p to test for a default constructor.

Thank you for the suggestion.  Attached is an incremental diff
with this tweak plus a test for it.

The code above has been there in the last three revisions of
the patch, so just to streamline the review/redo/retest process:
are there any other changes you'd like me to make?

Martin
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6e0951e..50c26bf 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8251,20 +8251,11 @@ has_trivial_copy_p (tree type, bool access, bool hasctor[2])
       if (TREE_CODE (f) != FUNCTION_DECL)
 	continue;
 
-      bool cpy_or_move_ctor_p;
-      if (TREE_CHAIN (DECL_ARGUMENTS (f)))
-	{
-	  /* Skip constructors that aren't copy or move ctors.  */
-	  if (!copy_fn_p (f))
-	    continue;
+      bool cpy_or_move_ctor_p = copy_fn_p (f);
 
-	  cpy_or_move_ctor_p = true;
-	}
-      else
-	{
-	  /* Constructor is a default ctor.  */
-	  cpy_or_move_ctor_p = false;
-	}
+      /* Skip ctors other than default, copy, and move.  */
+      if (!cpy_or_move_ctor_p && !default_ctor_p (f))
+	continue;
 
       if (DECL_DELETED_FN (f))
 	continue;
@@ -8346,7 +8337,7 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args)
      accessible.  */
   bool trivassign = has_trivial_copy_assign_p (desttype, true, &hasassign);
 
-  /* Set to true if DESTTYPE has an accessible defqault and copy ctor,
+  /* Set to true if DESTTYPE has an accessible default and copy ctor,
      respectively.  */
   bool hasctors[2] = { false, false };
 
diff --git a/gcc/testsuite/g++.dg/Wclass-memaccess.C b/gcc/testsuite/g++.dg/Wclass-memaccess.C
index d7ba44f..4783438 100644
--- a/gcc/testsuite/g++.dg/Wclass-memaccess.C
+++ b/gcc/testsuite/g++.dg/Wclass-memaccess.C
@@ -314,9 +314,11 @@ void test (HasCopy *p, const HasCopy &x,
   const int i = *ia;
   const size_t n = *ia;
 
-  // Zeroing out is diagnosed because value initialization is
-  // invalid (the copy ctor makes no default ctor unavailable).
-  T (bzero, (p, sizeof *p));        // { dg-warning "bzero" }
+  // Zeroing out is diagnosed because value initialization is invalid
+  // (the copy ctor makes no default ctor unavailable).  Since the type
+  // has no default ctor verify that the suggested alternative does not
+  // include value-initialization.
+  T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasCopy.; use assignment instead" }
   T (memset, (p, 0, sizeof *p));    // { dg-warning "memset" }
   T (memset, (p, 1, sizeof *p));    // { dg-warning "memset" }
   T (memset, (p, i, sizeof *p));    // { dg-warning "memset" }
@@ -350,6 +352,27 @@ void test (HasCopy *p, const HasCopy &x,
 
 #endif
 
+#if !defined TEST || TEST == TEST_HAS_DEFAULT_AND_COPY
+
+/* HasDefaultAndCopy is like HasCopy above but its default ctor takes
+   a default argument to verify that the suggested alternative offered
+   by the warning includes the default ctor (i.e., the test verifies
+   that the default ctor is recognized as such despite taking an argument.  */
+
+struct HasDefaultAndCopy
+{
+  HasDefaultAndCopy (int = 0);   // default ctor
+  HasDefaultAndCopy (const HasDefaultAndCopy&);
+};
+
+void test (HasDefaultAndCopy *p, const HasDefaultAndCopy &x)
+{
+  T (bzero, (p, sizeof *p));        // { dg-warning "clearing an object of non-trivial type .struct HasDefaultAndCopy.; use assignment or value-initialization instead" }
+  T (memset, (p, 0, sizeof *p));    // { dg-warning "clearing an object of non-trivial type .struct HasDefaultAndCopy.; use assignment or value-initialization instead" }
+}
+
+#endif
+
 #if !defined TEST || TEST == TEST_HAS_PRIVATE_COPY
 
 /* HasPrivateCopy cannot be copied using memcpy or memmove.  Since it's

Reply via email to