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