From b0e0b31f6fc59a5993329d7219d675ef068f2468 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 15 Sep 1998 11:43:54 +0000 Subject: [PATCH] cp-tree.h: Revert previous change. * cp-tree.h: Revert previous change. (finish_struct_methods): Remove declaration. * class.c: Revert previous change. (maybe_warn_about_overly_private_class): New function. (finish_struct_methods): Declare here, and make static. Remove unnecessary parameters. Tidy slightly. Use maybe_warn_about_overly_private_class. (finish_struct_1): Adjust. Remove check for private constructors, now done elsewhere. (finish_struct): Adjust. From-SVN: r22426 --- gcc/cp/ChangeLog | 21 ++ gcc/cp/class.c | 249 +++++++++++------- gcc/cp/cp-tree.h | 8 +- .../g++.old-deja/g++.benjamin/tem03.C | 6 +- .../g++.old-deja/g++.benjamin/tem04.C | 2 +- .../g++.old-deja/g++.jason/tempcons.C | 2 +- gcc/testsuite/g++.old-deja/g++.other/warn3.C | 54 ++++ gcc/testsuite/g++.old-deja/g++.pt/memclass8.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/typedef1.C | 2 +- gcc/testsuite/g++.old-deja/g++.robertl/eb28.C | 2 +- gcc/testsuite/g++.old-deja/g++.robertl/eb29.C | 2 +- 12 files changed, 239 insertions(+), 113 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/warn3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9ed5652f39f..2531b0edfb4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +1998-09-15 Mark Mitchell + + * cp-tree.h: Revert previous change. + (finish_struct_methods): Remove declaration. + * class.c: Revert previous change. + (maybe_warn_about_overly_private_class): New function. + (finish_struct_methods): Declare here, and make static. Remove + unnecessary parameters. Tidy slightly. Use + maybe_warn_about_overly_private_class. + (finish_struct_1): Adjust. Remove check for private constructors, + now done elsewhere. + (finish_struct): Adjust. + 1998-09-15 Andrew MacLeod * except.c (expand_start_catch_block): No need to check for new @@ -15,6 +28,14 @@ 1998-09-14 Mark Mitchell + * 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. + * pt.c (check_specialization_scope): Fix spelling error. (check_explicit_specialization): Remove code to handle explicit specializations in class scope; they are now correctly diagnosed diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 83c33cfd410..8b5d418f9b5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -100,7 +100,8 @@ 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)); +static void finish_struct_methods PROTO((tree)); +static void maybe_warn_about_overly_private_class PROTO ((tree)); /* Way of stacking language names. */ tree *current_lang_base, *current_lang_stack; @@ -1898,32 +1899,145 @@ 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". */ +/* Issue warnings about T having private constructors, but no friends, + and so forth. -static int -maybe_class_too_private_p (t) - tree t; + HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or + static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any + non-private static member functions. */ + +static void +maybe_warn_about_overly_private_class (t) + tree t; { - if (!warn_ctor_dtor_privacy) - /* The user doesn't want to here these warnings. */ - return 0; + if (warn_ctor_dtor_privacy + /* If the class has friends, those entities might create and + access instances, so we should not warn. */ + && !(CLASSTYPE_FRIEND_CLASSES (t) + || DECL_FRIENDLIST (TYPE_MAIN_DECL (t))) + /* We will have warned when the template was declared; there's + no need to warn on every instantiation. */ + && !CLASSTYPE_TEMPLATE_INSTANTIATION (t)) + { + /* We only issue one warning, if more than one applies, because + otherwise, on code like: - 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; + class A { + // Oops - forgot `public:' + A(); + A(const A&); + ~A(); + }; - 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; + we warn several times about essentially the same problem. */ - return 1; + int has_member_fn = 0; + int has_nonprivate_method = 0; + tree fn; + + /* Check to see if all (non-constructor, non-destructor) member + functions are private. (Since there are no friends or + non-private statics, we can't ever call any of the private + member functions.) */ + for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) + /* We're not interested in compiler-generated methods; they + don't provide any way to call private members. */ + if (!DECL_ARTIFICIAL (fn)) + { + if (!TREE_PRIVATE (fn)) + { + if (DECL_STATIC_FUNCTION_P (fn)) + /* A non-private static member function is just like a + friend; it can create and invoke private member + functions, and be accessed without a class + instance. */ + return; + + has_nonprivate_method = 1; + break; + } + else + has_member_fn = 1; + } + + if (!has_nonprivate_method && has_member_fn) + { + int i; + tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); + for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++) + if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) + || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) + { + has_nonprivate_method = 1; + break; + } + if (!has_nonprivate_method) + { + cp_warning ("all member functions in class `%T' are private", t); + return; + } + } + + /* Even if some of the member functions are non-private, the + class won't be useful for much if all the constructors or + destructors are private: such an object can never be created + or destroyed. */ + if (TYPE_HAS_DESTRUCTOR (t)) + { + tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1); + + if (TREE_PRIVATE (dtor)) + { + cp_warning ("`%#T' only defines a private destructor and has no friends", + t); + return; + } + } + + if (TYPE_HAS_CONSTRUCTOR (t)) + { + int nonprivate_ctor = 0; + + /* If a non-template class does not define a copy + constructor, one is defined for it, enabling it to avoid + this warning. For a template class, this does not + happen, and so we would normally get a warning on: + + template class C { private: C(); }; + + To avoid this asymmetry, we check TYPE_HAS_INIT_REF. */ + if (!TYPE_HAS_INIT_REF (t)) + nonprivate_ctor = 1; + else + for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); + fn; + fn = OVL_NEXT (fn)) + { + tree ctor = OVL_CURRENT (fn); + /* 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 (ctor)) + { + nonprivate_ctor = 1; + break; + } + } + + if (nonprivate_ctor == 0) + { + cp_warning ("`%#T' only defines private constructors and has no friends", + t); + return; + } + } + } } + /* Warn about duplicate methods in fn_fields. Also compact method lists so that lookup can be made faster. @@ -1945,16 +2059,14 @@ maybe_class_too_private_p (t) We also link each field which has shares a name with its baseclass to the head of the list of fields for that base class. This allows us to reduce search time in places like `build_method_call' to - consider only reasonably likely functions. */ + consider only reasonably likely functions. */ -tree -finish_struct_methods (t, fn_fields, nonprivate_method) +static void +finish_struct_methods (t) tree t; - tree fn_fields; - int nonprivate_method; { + tree fn_fields; tree method_vec; - tree save_fn_fields = fn_fields; tree ctor_name = constructor_name (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); @@ -1972,8 +2084,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method) /* First fill in entry 0 with the constructors, entry 1 with destructors, and the next few with type conversion operators (if any). */ - - for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) + for (fn_fields = TYPE_METHODS (t); fn_fields; + fn_fields = TREE_CHAIN (fn_fields)) { tree fn_name = DECL_NAME (fn_fields); @@ -2021,8 +2133,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method) grow_method (fn_fields, &method_vec); } - fn_fields = save_fn_fields; - for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) + for (fn_fields = TYPE_METHODS (t); fn_fields; + fn_fields = TREE_CHAIN (fn_fields)) { tree fn_name = DECL_NAME (fn_fields); @@ -2050,33 +2162,14 @@ finish_struct_methods (t, fn_fields, nonprivate_method) obstack_finish (&class_obstack); CLASSTYPE_METHOD_VEC (t) = method_vec; - if (nonprivate_method == 0 && maybe_class_too_private_p (t)) - { - tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); - for (i = 0; i < n_baseclasses; i++) - if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) - || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) - { - nonprivate_method = 1; - break; - } - if (nonprivate_method == 0) - cp_warning ("all member functions in class `%T' are private", t); - } - - /* Warn if all destructors are private (in which case this class is - effectively unusable. */ - if (TYPE_HAS_DESTRUCTOR (t)) - { - tree dtor = TREE_VEC_ELT (method_vec, 1); - - /* Wild parse errors can cause this to happen. */ - if (dtor == NULL_TREE) - TYPE_HAS_DESTRUCTOR (t) = 0; - else if (TREE_PRIVATE (dtor) && maybe_class_too_private_p (t)) - cp_warning ("`%#T' only defines a private destructor and has no friends", - t); - } + if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1)) + /* We thought there was a destructor, but there wasn't. Some + parse errors cause this anomalous situation. */ + TYPE_HAS_DESTRUCTOR (t) = 0; + + /* Issue warnings about private constructors and such. If there are + no methods, then some public defaults are generated. */ + maybe_warn_about_overly_private_class (t); /* Now for each member function (except for constructors and destructors), compute where member functions of the same @@ -2102,8 +2195,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method) else obstack_free (current_obstack, baselink_vec); } - - return method_vec; } /* Emit error when a duplicate definition of a type is seen. Patch up. */ @@ -3063,7 +3154,6 @@ finish_struct_1 (t, warn_anon) int any_default_members = 0; int const_sans_init = 0; int ref_sans_init = 0; - int nonprivate_method = 0; tree access_decls = NULL_TREE; int aggregate = 1; int empty = 1; @@ -3165,8 +3255,6 @@ finish_struct_1 (t, warn_anon) { GNU_xref_member (current_class_name, x); - nonprivate_method |= ! TREE_PRIVATE (x); - /* If this was an evil function, don't keep it in class. */ if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) continue; @@ -3538,9 +3626,6 @@ finish_struct_1 (t, warn_anon) /* Synthesize any needed methods. Note that methods will be synthesized for anonymous unions; grok_x_components undoes that. */ - if (! fn_fields) - nonprivate_method = 1; - if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) && !IS_SIGNATURE (t)) { @@ -3561,7 +3646,6 @@ finish_struct_1 (t, warn_anon) if (DECL_VINDEX (dtor)) add_virtual_function (&pending_virtuals, &pending_hard_virtuals, &has_virtual, dtor, t); - nonprivate_method = 1; } } @@ -3632,28 +3716,8 @@ finish_struct_1 (t, warn_anon) if (fn_fields) { TYPE_METHODS (t) = fn_fields; - method_vec = finish_struct_methods (t, fn_fields, nonprivate_method); - - if (TYPE_HAS_CONSTRUCTOR (t) - && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE) - { - int nonprivate_ctor = 0; - tree ctor; - - for (ctor = TREE_VEC_ELT (method_vec, 0); - ctor; - ctor = OVL_NEXT (ctor)) - if (! TREE_PRIVATE (OVL_CURRENT (ctor))) - { - nonprivate_ctor = 1; - break; - } - - if (nonprivate_ctor == 0 && maybe_class_too_private_p (t)) - cp_warning ("`%#T' only defines private constructors and has no friends", - t); - } + finish_struct_methods (t); + method_vec = CLASSTYPE_METHOD_VEC (t); } else { @@ -4229,12 +4293,6 @@ 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); @@ -4363,8 +4421,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) = tree_cons (NULL_TREE, d, DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))); } - CLASSTYPE_METHOD_VEC (t) - = finish_struct_methods (t, TYPE_METHODS (t), 1); + finish_struct_methods (t); TYPE_SIZE (t) = integer_zero_node; } else diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b58c06e9165..1f4bc0e2774 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -621,12 +621,11 @@ 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 : 10; + unsigned dummy : 11; } type_flags; int n_ancestors; @@ -1452,10 +1451,6 @@ 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) @@ -2414,7 +2409,6 @@ extern tree get_vfield_offset PROTO((tree)); extern void duplicate_tag_error PROTO((tree)); extern tree finish_struct PROTO((tree, tree, tree, int)); extern tree finish_struct_1 PROTO((tree, int)); -extern tree finish_struct_methods PROTO((tree, tree, int)); extern int resolves_to_fixed_type_p PROTO((tree, int *)); extern void init_class_processing PROTO((void)); extern int is_empty_class PROTO((tree)); diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C index 44e8ad87937..b74e2640203 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C @@ -80,7 +80,7 @@ public: // 04 // local names (14.6.1 p 4) -template class Xfour {// ERROR - .* +template struct Xfour {// ERROR - .* int T10; // ERROR - .* void f(){ char T10; // ERROR - .* @@ -90,7 +90,7 @@ template class Xfour {// ERROR - .* // 05 // using different tempate-parms for out-of-line defs -template class Xfive { +template struct Xfive { void f(); }; @@ -189,7 +189,7 @@ public: // 13 // member templates, non-type parameters template // ERROR - .* -class Xthirteen { +struct Xthirteen { template long comp_ge(long test) {// ERROR - . long local_value; if (local_value > value) diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/tem04.C b/gcc/testsuite/g++.old-deja/g++.benjamin/tem04.C index 3bed81e6ffe..0330d0bbd0a 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/tem04.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/tem04.C @@ -112,7 +112,7 @@ protected: // 20 // local names (14.6.1 p 4) part two, variable names as template param -template class Xtwenty { +template struct Xtwenty { void f(){ T17 my_type; //ok for (int j = 0; j < 5; ++l) diff --git a/gcc/testsuite/g++.old-deja/g++.jason/tempcons.C b/gcc/testsuite/g++.old-deja/g++.jason/tempcons.C index bbc6afeb77e..77cc732090e 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/tempcons.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/tempcons.C @@ -2,7 +2,7 @@ // Build don't link: template -class A { +struct A { int i; Blarg () : i(0) { } // ERROR - }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/warn3.C b/gcc/testsuite/g++.old-deja/g++.other/warn3.C new file mode 100644 index 00000000000..4827c5645f2 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/warn3.C @@ -0,0 +1,54 @@ +// Build don't link: + +class A { +}; + + +class B { +public: + void f(); + +private: + B (); + B (const B&); +}; // WARNING - only private constructors + + +class C { +public: + void f(); + +private: + ~C (); +}; // WARNING - only private destructors + + +class D { +private: + void f(); +}; // WARNING - all member functions are private + + +template +class X { +private: + ~X (); +}; // WARNING - only private destructors + +template class X; +template class X; + + +template +class Y { +private: + Y (); + Y (const Y&); +}; // WARNING - only private constructors + + +template +class Z { +private: + void f(); +}; // WARNING - all member functions are private diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass8.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass8.C index c0bf0cd83ab..431d41d64e8 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memclass8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass8.C @@ -4,7 +4,7 @@ template class S { template - class S2 { + struct S2 { S2(const S2& s2u) {} }; }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C index 99e4f7299eb..7358d7225f7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C @@ -1,7 +1,7 @@ // Build don't link: // GROUPS passed membertemplates template -class S +struct S { S(const S& x) {} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typedef1.C b/gcc/testsuite/g++.old-deja/g++.pt/typedef1.C index 5de152ef7dc..8d674c9f127 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typedef1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typedef1.C @@ -2,7 +2,7 @@ // Build don't link: template -class A +struct A { typedef enum { diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb28.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb28.C index 5fe707a2fa3..6c3130eafa5 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb28.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb28.C @@ -6,7 +6,7 @@ class a vector vs; friend class b; }; -class b +struct b { vector va; operator vector< vector >() diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb29.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb29.C index d1dc6a2ef9b..f1017a774a7 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb29.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb29.C @@ -6,7 +6,7 @@ class a vector vs; friend class b; }; -class b +struct b { vector va; operator vector< vector >()