OSDN Git Service

* cp-tree.h: Revert previous change.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 1998 11:43:54 +0000 (11:43 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 1998 11:43:54 +0000 (11:43 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22426 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C
gcc/testsuite/g++.old-deja/g++.benjamin/tem04.C
gcc/testsuite/g++.old-deja/g++.jason/tempcons.C
gcc/testsuite/g++.old-deja/g++.other/warn3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memclass8.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp60.C
gcc/testsuite/g++.old-deja/g++.pt/typedef1.C
gcc/testsuite/g++.old-deja/g++.robertl/eb28.C
gcc/testsuite/g++.old-deja/g++.robertl/eb29.C

index 9ed5652..2531b0e 100644 (file)
@@ -1,3 +1,16 @@
+1998-09-15  Mark Mitchell  <mark@markmitchell.com>
+
+       * 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  <amacleod@cygnus.com>
 
        * except.c (expand_start_catch_block): No need to check for new
 
 1998-09-14  Mark Mitchell  <mark@markmitchell.com>
 
+       * 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
index 83c33cf..8b5d418 100644 (file)
@@ -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:
+
+          class A {
+            // Oops - forgot `public:'
+            A();
+            A(const A&);
+            ~A();
+          };
+
+        we warn several times about essentially the same problem.  */
+
+      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 (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 (!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;
+           }
+       }
 
-  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;
+      /* 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:
 
-  return 1;
+              template <class T> 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
index b58c06e..1f4bc0e 100644 (file)
@@ -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));
index 44e8ad8..b74e264 100644 (file)
@@ -80,7 +80,7 @@ public:
 
 // 04
 // local names (14.6.1 p 4)
-template <class T10, int i> class Xfour {// ERROR - .*
+template <class T10, int i> struct Xfour {// ERROR - .*
   int T10; // ERROR - .*
   void f(){
     char T10; // ERROR - .*
@@ -90,7 +90,7 @@ template <class T10, int i> class Xfour {// ERROR - .*
 
 // 05
 // using different tempate-parms for out-of-line defs
-template <class T12, int i> class Xfive {
+template <class T12, int i> struct Xfive {
   void f();
 };
 
@@ -189,7 +189,7 @@ public:
 // 13
 // member templates, non-type parameters
 template <long l>// ERROR - .*
-class Xthirteen {
+struct Xthirteen {
   template <long l> long comp_ge(long test) {// ERROR - .
     long local_value;
     if (local_value > value) 
index 3bed81e..0330d0b 100644 (file)
@@ -112,7 +112,7 @@ protected:
 
 // 20
 // local names (14.6.1 p 4) part two, variable names as template param
-template <class T17, int i> class Xtwenty {
+template <class T17, int i> struct Xtwenty {
   void f(){
     T17 my_type; //ok
     for (int j = 0; j < 5; ++l)
index bbc6afe..77cc732 100644 (file)
@@ -2,7 +2,7 @@
 // Build don't link:
 
 template <class T>
-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 (file)
index 0000000..4827c56
--- /dev/null
@@ -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 T>
+class X {
+private:
+  ~X (); 
+}; // WARNING - only private destructors
+
+template class X<int>;
+template class X<double>;
+
+
+template <class T>
+class Y {
+private:
+  Y (); 
+  Y (const Y&);
+}; // WARNING - only private constructors
+
+
+template <class T>
+class Z {
+private:
+  void f(); 
+}; // WARNING - all member functions are private
index c0bf0cd..431d41d 100644 (file)
@@ -4,7 +4,7 @@ template <class T>
 class S
 {
   template <class U>
-  class S2 {
+  struct S2 {
     S2(const S2<U>& s2u) {}
   };
 };
index 99e4f72..7358d72 100644 (file)
@@ -1,7 +1,7 @@
 // Build don't link:
 // GROUPS passed membertemplates
 template <class T>
-class S
+struct S
 {
   S(const S<T>& x)  {}
 
index 5de152e..8d674c9 100644 (file)
@@ -2,7 +2,7 @@
 // Build don't link:
 
 template <class T>
-class A
+struct A
 {
   typedef enum
   {
index 5fe707a..6c3130e 100644 (file)
@@ -6,7 +6,7 @@ class a
         vector<s> vs;
         friend class b;
 };
-class b
+struct b
 {
         vector<a> va;
         operator vector< vector<s> >()
index d1dc6a2..f1017a7 100644 (file)
@@ -6,7 +6,7 @@ class a
         vector<s> vs;
         friend class b;
 };
-class b
+struct b
 {
         vector<a> va;
         operator vector< vector<s> >()