summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/class.c24
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C20
4 files changed, 42 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index acf179b0c84..fef4c21871d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2017-07-17 Nathan Sidwell <nathan@acm.org>
+ * class.c (maybe_warn_about_overly_private_class): Ignore public
+ copy ctors.
+
* class.c (type_has_user_declared_move_constructor,
type_has_user_declared_move_assign): Combine into ...
(classtype_has_user_move_assign_or_move_ctor_p): ... this new function.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b2175864e52..0336ae5f143 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2240,10 +2240,10 @@ maybe_warn_about_overly_private_class (tree t)
/* Warn about classes that have private constructors and no friends. */
if (TYPE_HAS_USER_CONSTRUCTOR (t)
/* Implicitly generated constructors are always public. */
- && (!CLASSTYPE_LAZY_DEFAULT_CTOR (t)
- || !CLASSTYPE_LAZY_COPY_CTOR (t)))
+ && !CLASSTYPE_LAZY_DEFAULT_CTOR (t))
{
bool nonprivate_ctor = false;
+ tree copy_or_move = NULL_TREE;
/* If a non-template class does not define a copy
constructor, one is defined for it, enabling it to avoid
@@ -2260,13 +2260,15 @@ maybe_warn_about_overly_private_class (tree t)
else
for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t));
!nonprivate_ctor && iter; ++iter)
- /* Ideally, we wouldn't count copy constructors (or, in
- fact, any constructor that takes an argument of the class
- type as a parameter) because such things cannot be used
- to construct an instance of the class unless you already
- have one. But, for now at least, we're more
- generous. */
- if (! TREE_PRIVATE (*iter))
+ if (TREE_PRIVATE (*iter))
+ continue;
+ else if (copy_fn_p (*iter) || move_fn_p (*iter))
+ /* Ideally, we wouldn't count any constructor that takes
+ an argument of the class type as a parameter, because
+ such things cannot be used to construct an instance of
+ the class unless you already have one. */
+ copy_or_move = *iter;
+ else
nonprivate_ctor = true;
if (!nonprivate_ctor)
@@ -2274,6 +2276,10 @@ maybe_warn_about_overly_private_class (tree t)
warning (OPT_Wctor_dtor_privacy,
"%q#T only defines private constructors and has no friends",
t);
+ if (copy_or_move)
+ inform (DECL_SOURCE_LOCATION (copy_or_move),
+ "%q#D is public, but requires an existing %q#T object",
+ copy_or_move, t);
return;
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5ff0141dde5..a0ca5143155 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-17 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/warn/ctor-dtor-privacy-3.C: New.
+
2017-07-17 Bernd Edlinger <bernd.edlinger@hotmail.de>
* lib/gcc-dg.exp: Increase expect's match buffer size.
diff --git a/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C
new file mode 100644
index 00000000000..93a42eac08d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wctor-dtor-privacy" }
+
+class X // { dg-message "only defines private" }
+{
+public:
+ X (X const &); // { dg-message "requires an existing" }
+};
+
+class Y // { dg-message "only defines private" }
+{
+public:
+ Y (Y &&); // { dg-message "requires an existing" }
+};
+
+class Z
+{
+public:
+ Z (int);
+};