class.c (maybe_warn_about_overly_private_class): Ignore public copy ctors.
authorNathan Sidwell <nathan@acm.org>
Mon, 17 Jul 2017 16:52:31 +0000 (16:52 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 17 Jul 2017 16:52:31 +0000 (16:52 +0000)
* class.c (maybe_warn_about_overly_private_class): Ignore public
copy ctors.

* g++.dg/warn/ctor-dtor-privacy-3.C: New.

From-SVN: r250281

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-3.C [new file with mode: 0644]

index acf179b0c8413398c19173490526569ed1be7716..fef4c21871d8e39548684d4f50f4141167eae97b 100644 (file)
@@ -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.
index b2175864e526622579e2a91a3ac6d0bb00c728dc..0336ae5f143622f908b52c147bdc739163b06d43 100644 (file)
@@ -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;
        }
     }
index 5ff0141dde530cd34b44263d655f5426bd3dc1b5..a0ca514315517b1015a4b1b5c81f90b3642d8da2 100644 (file)
@@ -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 (file)
index 0000000..93a42ea
--- /dev/null
@@ -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);
+};