From aed7b2a6e211e002aa7bda1f58fe4269bf7a5fcc Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 14 Sep 1998 11:09:07 +0000 Subject: [PATCH] cp-tree.h (lang_type): Add has_non_private_static_mem_fn. * 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 | 47 +++++++++++++++---- gcc/cp/cp-tree.h | 7 ++- .../g++.old-deja/g++.other/singleton.C | 2 +- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e5863a4194d..83c33cfd410 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4dbfc9e6c3a..b58c06e9165 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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) diff --git a/gcc/testsuite/g++.old-deja/g++.other/singleton.C b/gcc/testsuite/g++.old-deja/g++.other/singleton.C index f2025fc1753..c2c481075ff 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/singleton.C +++ b/gcc/testsuite/g++.old-deja/g++.other/singleton.C @@ -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;