OSDN Git Service

When a class template is explicitly instantiated, its member should be too.
[pf3gnuchains/gcc-fork.git] / gcc / cp / search.c
index cee35ff..5f4c91c 100644 (file)
@@ -1,7 +1,7 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -125,7 +125,7 @@ push_search_level (struct stack_level *stack, struct obstack *obstack)
 static struct search_level *
 pop_search_level (struct stack_level *obstack)
 {
-  register struct search_level *stack = pop_stack_level (obstack);
+  struct search_level *stack = pop_stack_level (obstack);
 
   return stack;
 }
@@ -210,7 +210,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
          
        case bk_same_type:
          bk = bk_proper_base;
-         /* FALLTHROUGH */
+         /* Fall through.  */
        case bk_proper_base:
          my_friendly_assert (found == bk_not_base, 20010723);
          found = bk;
@@ -231,6 +231,33 @@ lookup_base_r (tree binfo, tree base, base_access access,
   return found;
 }
 
+/* Returns true if type BASE is accessible in T.  (BASE is known to be
+   a (possibly non-proper) base class of T.)  */
+
+bool
+accessible_base_p (tree t, tree base)
+{
+  tree decl;
+
+  /* [class.access.base]
+
+     A base class is said to be accessible if an invented public
+     member of the base class is accessible.  
+
+     If BASE is a non-proper base, this condition is trivially
+     true.  */
+  if (same_type_p (t, base))
+    return true;
+  /* Rather than inventing a public member, we use the implicit
+     public typedef created in the scope of every class.  */
+  decl = TYPE_FIELDS (base);
+  while (!DECL_SELF_REFERENCE_P (decl))
+    decl = TREE_CHAIN (decl);
+  while (ANON_AGGR_TYPE_P (t))
+    t = TYPE_CONTEXT (t);
+  return accessible_p (t, decl);
+}
+
 /* Lookup BASE in the hierarchy dominated by T.  Do access checking as
    ACCESS specifies.  Return the binfo we discover.  If KIND_PTR is
    non-NULL, fill with information about what kind of base we
@@ -287,41 +314,24 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
        break;
 
       default:
-       if (access != ba_ignore
+       if ((access & ~ba_quiet) != ba_ignore
            /* If BASE is incomplete, then BASE and TYPE are probably
               the same, in which case BASE is accessible.  If they
               are not the same, then TYPE is invalid.  In that case,
               there's no need to issue another error here, and
               there's no implicit typedef to use in the code that
               follows, so we skip the check.  */
-           && COMPLETE_TYPE_P (base))
+           && COMPLETE_TYPE_P (base)
+           && !accessible_base_p (t, base))
          {
-           tree decl;
-
-           /* [class.access.base]
-
-              A base class is said to be accessible if an invented public
-              member of the base class is accessible.  */
-           /* Rather than inventing a public member, we use the implicit
-              public typedef created in the scope of every class.  */
-           decl = TYPE_FIELDS (base);
-           while (TREE_CODE (decl) != TYPE_DECL
-                  || !DECL_ARTIFICIAL (decl)
-                  || DECL_NAME (decl) != constructor_name (base))
-             decl = TREE_CHAIN (decl);
-           while (ANON_AGGR_TYPE_P (t))
-             t = TYPE_CONTEXT (t);
-           if (!accessible_p (t, decl))
+           if (!(access & ba_quiet))
              {
-               if (!(access & ba_quiet))
-                 {
-                   error ("`%T' is an inaccessible base of `%T'", base, t);
-                   binfo = error_mark_node;
-                 }
-               else
-                 binfo = NULL_TREE;
-               bk = bk_inaccessible;
+               error ("`%T' is an inaccessible base of `%T'", base, t);
+               binfo = error_mark_node;
              }
+           else
+             binfo = NULL_TREE;
+           bk = bk_inaccessible;
          }
        break;
       }
@@ -417,7 +427,7 @@ get_dynamic_cast_base_type (tree subtype, tree target)
 tree
 lookup_field_1 (tree type, tree name, bool want_type)
 {
-  register tree field;
+  tree field;
 
   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
       || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
@@ -434,8 +444,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
       && DECL_LANG_SPECIFIC (TYPE_NAME (type))
       && DECL_SORTED_FIELDS (TYPE_NAME (type)))
     {
-      tree *fields = &TREE_VEC_ELT (DECL_SORTED_FIELDS (TYPE_NAME (type)), 0);
-      int lo = 0, hi = TREE_VEC_LENGTH (DECL_SORTED_FIELDS (TYPE_NAME (type)));
+      tree *fields = &DECL_SORTED_FIELDS (TYPE_NAME (type))->elts[0];
+      int lo = 0, hi = DECL_SORTED_FIELDS (TYPE_NAME (type))->len;
       int i;
 
       while (lo < hi)
@@ -538,7 +548,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
    function.  If so, we know to put the decls into the class's scope.  */
 
 tree
-current_scope ()
+current_scope (void)
 {
   if (current_function_decl == NULL_TREE)
     return current_class_type;
@@ -560,7 +570,7 @@ current_scope ()
    not within a member function body of the local class.  */
 
 int
-at_function_scope_p ()
+at_function_scope_p (void)
 {
   tree cs = current_scope ();
   return cs && TREE_CODE (cs) == FUNCTION_DECL;
@@ -569,12 +579,22 @@ at_function_scope_p ()
 /* Returns true if the innermost active scope is a class scope.  */
 
 bool
-at_class_scope_p ()
+at_class_scope_p (void)
 {
   tree cs = current_scope ();
   return cs && TYPE_P (cs);
 }
 
+/* Returns true if the innermost active scope is a namespace scope.  */
+
+bool
+at_namespace_scope_p (void)
+{
+  /* We are in a namespace scope if we are not it a class scope or a
+     function scope.  */
+  return !current_scope();
+}
+
 /* Return the scope of DECL, as appropriate when doing name-lookup.  */
 
 tree
@@ -597,7 +617,7 @@ context_for_name_lookup (tree decl)
 }
 
 /* The accessibility routines use BINFO_ACCESS for scratch space
-   during the computation of the accssibility of some declaration.  */
+   during the computation of the accessibility of some declaration.  */
 
 #define BINFO_ACCESS(NODE) \
   ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
@@ -620,7 +640,7 @@ dfs_access_in_type (tree binfo, void *data)
 
   if (context_for_name_lookup (decl) == type)
     {
-      /* If we have desceneded to the scope of DECL, just note the
+      /* If we have descended to the scope of DECL, just note the
         appropriate access.  */
       if (TREE_PRIVATE (decl))
        access = ak_private;
@@ -734,7 +754,7 @@ access_in_type (tree type, tree decl)
   return BINFO_ACCESS (binfo);
 }
 
-/* Called from dfs_accessible_p via dfs_walk.  */
+/* Called from accessible_p via dfs_walk.  */
 
 static tree
 dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
@@ -753,20 +773,17 @@ dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
   return binfo;
 }
 
-/* Called from dfs_accessible_p via dfs_walk.  */
+/* Called from accessible_p via dfs_walk.  */
 
 static tree
-dfs_accessible_p (tree binfo, void *data)
+dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
 {
-  int protected_ok = data != 0;
   access_kind access;
 
   BINFO_MARKED (binfo) = 1;
   access = BINFO_ACCESS (binfo);
-  if (access == ak_public || (access == ak_protected && protected_ok))
-    return binfo;
-  else if (access != ak_none
-          && is_friend (BINFO_TYPE (binfo), current_scope ()))
+  if (access != ak_none
+      && is_friend (BINFO_TYPE (binfo), current_scope ()))
     return binfo;
 
   return NULL_TREE;
@@ -893,6 +910,8 @@ accessible_p (tree type, tree decl)
 {
   tree binfo;
   tree t;
+  tree scope;
+  access_kind access;
 
   /* Nonzero if it's OK to access DECL if it has protected
      accessibility in TYPE.  */
@@ -903,6 +922,18 @@ accessible_p (tree type, tree decl)
   if (!TYPE_P (context_for_name_lookup (decl)))
     return 1;
 
+  /* There is no need to perform access checks inside a thunk.  */
+  scope = current_scope ();
+  if (scope && DECL_THUNK_P (scope))
+    return 1;
+
+  /* In a template declaration, we cannot be sure whether the
+     particular specialization that is instantiated will be a friend
+     or not.  Therefore, all access checks are deferred until
+     instantiation.  */
+  if (processing_template_decl)
+    return 1;
+
   if (!TYPE_P (type))
     {
       binfo = type;
@@ -938,7 +969,7 @@ accessible_p (tree type, tree decl)
 
   /* Now, loop through the classes of which we are a friend.  */
   if (!protected_ok)
-    protected_ok = friend_accessible_p (current_scope (), decl, binfo);
+    protected_ok = friend_accessible_p (scope, decl, binfo);
 
   /* Standardize the binfo that access_in_type will use.  We don't
      need to know what path was chosen from this point onwards.  */
@@ -946,18 +977,22 @@ accessible_p (tree type, tree decl)
 
   /* Compute the accessibility of DECL in the class hierarchy
      dominated by type.  */
-  access_in_type (type, decl);
-  /* Walk the hierarchy again, looking for a base class that allows
-     access.  */
-  t = dfs_walk (binfo, dfs_accessible_p, 
-               dfs_accessible_queue_p,
-               protected_ok ? &protected_ok : 0);
-  /* Clear any mark bits.  Note that we have to walk the whole tree
-     here, since we have aborted the previous walk from some point
-     deep in the tree.  */
-  dfs_walk (binfo, dfs_unmark, 0,  0);
-
-  return t != NULL_TREE;
+  access = access_in_type (type, decl);
+  if (access == ak_public
+      || (access == ak_protected && protected_ok))
+    return 1;
+  else
+    {
+      /* Walk the hierarchy again, looking for a base class that allows
+        access.  */
+      t = dfs_walk (binfo, dfs_accessible_p, dfs_accessible_queue_p, 0);
+      /* Clear any mark bits.  Note that we have to walk the whole tree
+        here, since we have aborted the previous walk from some point
+        deep in the tree.  */
+      dfs_walk (binfo, dfs_unmark, 0,  0);
+
+      return t != NULL_TREE;
+    }
 }
 
 struct lookup_field_info {
@@ -1673,7 +1708,10 @@ check_final_overrider (tree overrider, tree basefn)
   tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
   tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
   int fail = 0;
-  
+
+  if (DECL_INVALID_OVERRIDER_P (overrider))
+    return 0;
+
   if (same_type_p (base_return, over_return))
     /* OK */;
   else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
@@ -1712,9 +1750,7 @@ check_final_overrider (tree overrider, tree basefn)
        {
          /* can_convert will permit user defined conversion from a
             (reference to) class type. We must reject them.  */
-         over_return = TREE_TYPE (over_type);
-         if (TREE_CODE (over_return) == REFERENCE_TYPE)
-           over_return = TREE_TYPE (over_return);
+         over_return = non_reference (TREE_TYPE (over_type));
          if (CLASS_TYPE_P (over_return))
            fail = 2;
        }
@@ -1725,8 +1761,6 @@ check_final_overrider (tree overrider, tree basefn)
     fail = 2;
   if (!fail)
     /* OK */;
-  else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
-    return 0;
   else
     {
       if (fail == 1)
@@ -1740,21 +1774,16 @@ check_final_overrider (tree overrider, tree basefn)
                       overrider);
          cp_error_at ("  overriding `%#D'", basefn);
        }
-      SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
-                                  DECL_CONTEXT (overrider));
+      DECL_INVALID_OVERRIDER_P (overrider) = 1;
       return 0;
     }
   
   /* Check throw specifier is at least as strict.  */
   if (!comp_except_specs (base_throw, over_throw, 0))
     {
-      if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
-       {
-         cp_error_at ("looser throw specifier for `%#F'", overrider);
-         cp_error_at ("  overriding `%#F'", basefn);
-         SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
-                                     DECL_CONTEXT (overrider));
-       }
+      cp_error_at ("looser throw specifier for `%#F'", overrider);
+      cp_error_at ("  overriding `%#F'", basefn);
+      DECL_INVALID_OVERRIDER_P (overrider) = 1;
       return 0;
     }
   
@@ -2113,6 +2142,20 @@ setup_class_bindings (tree name, int type_binding_p)
          if (BASELINK_P (value_binding))
            /* NAME is some overloaded functions.  */
            value_binding = BASELINK_FUNCTIONS (value_binding);
+         /* Two conversion operators that convert to the same type
+            may have different names.  (See
+            mangle_conv_op_name_for_type.)  To avoid recording the
+            same conversion operator declaration more than once we
+            must check to see that the same operator was not already
+            found under another name.  */
+         if (IDENTIFIER_TYPENAME_P (name)
+             && is_overloaded_fn (value_binding))
+           {
+             tree fns;
+             for (fns = value_binding; fns; fns = OVL_NEXT (fns))
+               if (IDENTIFIER_CLASS_VALUE (DECL_NAME (OVL_CURRENT (fns))))
+                 return;
+           }
          pushdecl_class_level (value_binding);
        }
     }
@@ -2211,7 +2254,18 @@ dfs_unuse_fields (tree binfo, void *data ATTRIBUTE_UNUSED)
   tree type = TREE_TYPE (binfo);
   tree fields;
 
-  for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+  if (TREE_CODE (type) == TYPENAME_TYPE)
+    fields = TYPENAME_TYPE_FULLNAME (type);
+  else if (TREE_CODE (type) == TYPEOF_TYPE)
+    fields = TYPEOF_TYPE_EXPR (type);
+  else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+          || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+          || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+    fields = TEMPLATE_TYPE_PARM_INDEX (type);
+  else
+    fields = TYPE_FIELDS (type);
+
+  for (; fields; fields = TREE_CHAIN (fields))
     {
       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
@@ -2232,7 +2286,7 @@ unuse_fields (tree type)
 }
 
 void
-pop_class_decls ()
+pop_class_decls (void)
 {
   /* We haven't pushed a search level when dealing with cached classes,
      so we'd better not try to pop it.  */
@@ -2241,7 +2295,7 @@ pop_class_decls ()
 }
 
 void
-print_search_statistics ()
+print_search_statistics (void)
 {
 #ifdef GATHER_STATISTICS
   fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
@@ -2255,13 +2309,13 @@ print_search_statistics ()
 }
 
 void
-init_search_processing ()
+init_search_processing (void)
 {
   gcc_obstack_init (&search_obstack);
 }
 
 void
-reinit_search_statistics ()
+reinit_search_statistics (void)
 {
 #ifdef GATHER_STATISTICS
   n_fields_searched = 0;
@@ -2297,8 +2351,27 @@ add_conversions (tree binfo, void *data)
       /* Make sure we don't already have this conversion.  */
       if (! IDENTIFIER_MARKED (name))
        {
-         *conversions = tree_cons (binfo, tmp, *conversions);
-         IDENTIFIER_MARKED (name) = 1;
+         tree t;
+
+         /* Make sure that we do not already have a conversion
+            operator for this type.  Merely checking the NAME is not
+            enough because two conversion operators to the same type
+            may not have the same NAME.  */
+         for (t = *conversions; t; t = TREE_CHAIN (t))
+           {
+             tree fn;
+             for (fn = TREE_VALUE (t); fn; fn = OVL_NEXT (fn))
+               if (same_type_p (TREE_TYPE (name),
+                                DECL_CONV_FN_TYPE (OVL_CURRENT (fn))))
+                 break;
+             if (fn)
+               break;
+           }
+         if (!t)
+           {
+             *conversions = tree_cons (binfo, tmp, *conversions);
+             IDENTIFIER_MARKED (name) = 1;
+           }
        }
     }
   return NULL_TREE;