cp-tree.h (lang_type): Add has_non_private_static_mem_fn.
authorMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 14 Sep 1998 11:09:07 +0000 (11:09 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 14 Sep 1998 11:09:07 +0000 (11:09 +0000)
* cp-tree.h (lang_type): Add has_non_private_static_mem_fn.
(CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN): New macro, to access it.
* class.c (maybe_class_too_private_p): New function.
(finish_struct_methods): Use it.
(finish_struct_1): Likewise.
(finish_struct): Set CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN if
appropriate.

From-SVN: r22415

gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/testsuite/g++.old-deja/g++.other/singleton.C

index e5863a4194deabb1b08631f376b0ab6cc556fdf6..83c33cfd41013e09183955e50ab364242dc2919e 100644 (file)
@@ -100,6 +100,7 @@ static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
                                               tree, tree));
 static void build_class_init_list PROTO((tree));
 static int finish_base_struct PROTO((tree, struct base_info *));
+static int maybe_class_too_private_p PROTO((tree));
 
 /* Way of stacking language names.  */
 tree *current_lang_base, *current_lang_stack;
@@ -1897,6 +1898,32 @@ grow_method (fndecl, method_vec_ptr)
     }
 }
 
+/* Returns non-zero if T is the sort of class for which we should
+   check issue warnings like "all constructors are private".  */
+
+static int
+maybe_class_too_private_p (t)
+    tree t;
+{
+  if (!warn_ctor_dtor_privacy)
+    /* The user doesn't want to here these warnings.  */
+    return 0;
+
+  if (CLASSTYPE_FRIEND_CLASSES (t) 
+      || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))
+    /* The class has friends.  Maybe they can make use of the class,
+       even though it's very private.  */
+    return 0;
+
+  if (CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN (t))
+    /* The class has a non-private static member function.  Such a
+       thing might be used, like a friend, to create instances of the
+       class.  */
+    return 0;
+
+  return 1;
+}
+
 /* Warn about duplicate methods in fn_fields.  Also compact method
    lists so that lookup can be made faster.
 
@@ -2023,9 +2050,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
   obstack_finish (&class_obstack);
   CLASSTYPE_METHOD_VEC (t) = method_vec;
 
-  if (nonprivate_method == 0
-      && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
-      && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
+  if (nonprivate_method == 0 && maybe_class_too_private_p (t))
     {
       tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
       for (i = 0; i < n_baseclasses; i++)
@@ -2035,8 +2060,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
            nonprivate_method = 1;
            break;
          }
-      if (nonprivate_method == 0 
-         && warn_ctor_dtor_privacy)
+      if (nonprivate_method == 0)
        cp_warning ("all member functions in class `%T' are private", t);
     }
 
@@ -2049,10 +2073,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
       /* Wild parse errors can cause this to happen.  */
       if (dtor == NULL_TREE)
        TYPE_HAS_DESTRUCTOR (t) = 0;
-      else if (TREE_PRIVATE (dtor)
-              && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
-              && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE
-              && warn_ctor_dtor_privacy)
+      else if (TREE_PRIVATE (dtor) && maybe_class_too_private_p (t))
        cp_warning ("`%#T' only defines a private destructor and has no friends",
                    t);
     }
@@ -3629,7 +3650,7 @@ finish_struct_1 (t, warn_anon)
                break;
              }
 
-         if (nonprivate_ctor == 0 && warn_ctor_dtor_privacy)
+         if (nonprivate_ctor == 0 && maybe_class_too_private_p (t))
            cp_warning ("`%#T' only defines private constructors and has no friends",
                        t);
        }
@@ -4208,6 +4229,12 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
          TREE_PRIVATE (x) = access == access_private_node;
          TREE_PROTECTED (x) = access == access_protected_node;
 
+         if (!TREE_PRIVATE (x) 
+             && TREE_CODE (x) == FUNCTION_DECL 
+             && DECL_LANG_SPECIFIC (x)
+             && DECL_STATIC_FUNCTION_P (x))
+           CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN (t) = 1;
+
          if (TREE_CODE (x) == TEMPLATE_DECL)
            {
              TREE_PRIVATE (DECL_RESULT (x)) = TREE_PRIVATE (x);
index 4dbfc9e6c3ac63572cb56c00e8420aedfda63a0b..b58c06e9165373f1b8e5af08311346d920008d27 100644 (file)
@@ -621,11 +621,12 @@ struct lang_type
       unsigned has_complex_assign_ref : 1;
       unsigned has_abstract_assign_ref : 1;
       unsigned non_aggregate : 1;
+      unsigned has_non_private_static_mem_fn : 1;
 
       /* The MIPS compiler gets it wrong if this struct also
         does not fill out to a multiple of 4 bytes.  Add a
         member `dummy' with new bits if you go over the edge.  */
-      unsigned dummy : 11;
+      unsigned dummy : 10;
     } type_flags;
 
   int n_ancestors;
@@ -1451,6 +1452,10 @@ extern int flag_new_for_scope;
 #define TYPE_NON_AGGREGATE_CLASS(NODE) \
   (IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
 
+/* Nonzero if NODE has a non-private static member function.  */
+#define CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN(NODE) \
+  (TYPE_LANG_SPECIFIC (NODE)->type_flags.has_non_private_static_mem_fn)
+
 /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
 #define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
 #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
index f2025fc1753fda226f51edec86c41e3b36ce29ce..c2c481075fffbf038952ffac28b64fedf723d6f4 100644 (file)
@@ -24,7 +24,7 @@ private:
        void operator=( const singleton& rhs );
        int initialized;
        static int counter;
-};  // gets bogus error - class is not useless XFAIL *-*-*
+};  
 
 int singleton::counter;