OSDN Git Service

PR c++/29020
[pf3gnuchains/gcc-fork.git] / gcc / cp / friend.c
index 2d177a0..d92df5f 100644 (file)
@@ -1,5 +1,5 @@
 /* Help friends in C++.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -78,33 +78,38 @@ is_friend (tree type, tree supplicant)
   else
     /* It's a type.  */
     {
-      /* Nested classes are implicitly friends of their enclosing types, as
-        per core issue 45 (this is a change from the standard).  */
-      for (context = supplicant;
-          context && TYPE_P (context);
-          context = TYPE_CONTEXT (context))
-       if (type == context)
-         return 1;
-      
+      if (same_type_p (supplicant, type))
+       return 1;
+
       list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
       for (; list ; list = TREE_CHAIN (list))
        {
          tree t = TREE_VALUE (list);
 
-         if (TREE_CODE (t) == TEMPLATE_DECL ? 
+         if (TREE_CODE (t) == TEMPLATE_DECL ?
              is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) :
              same_type_p (supplicant, t))
            return 1;
        }
-    }      
+    }
 
-  if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
-    context = DECL_CONTEXT (supplicant);
-  else if (! declp)
-    /* Local classes have the same access as the enclosing function.  */
-    context = decl_function_context (TYPE_MAIN_DECL (supplicant));
+  if (declp)
+    {
+      if (DECL_FUNCTION_MEMBER_P (supplicant))
+       context = DECL_CONTEXT (supplicant);
+      else
+       context = NULL_TREE;
+    }
   else
-    context = NULL_TREE;
+    {
+      if (TYPE_CLASS_SCOPE_P (supplicant))
+       /* Nested classes get the same access as their enclosing types, as
+          per DR 45 (this is a change from the standard).  */
+       context = TYPE_CONTEXT (supplicant);
+      else
+       /* Local classes have the same access as the enclosing function.  */
+       context = decl_function_context (TYPE_MAIN_DECL (supplicant));
+    }
 
   /* A namespace is not friend to anybody.  */
   if (context && TREE_CODE (context) == NAMESPACE_DECL)
@@ -149,7 +154,7 @@ add_friend (tree type, tree decl, bool complain)
              if (decl == TREE_VALUE (friends))
                {
                  if (complain)
-                   warning ("%qD is already a friend of class %qT",
+                   warning (0, "%qD is already a friend of class %qT",
                             decl, type);
                  return;
                }
@@ -174,7 +179,7 @@ add_friend (tree type, tree decl, bool complain)
     = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
                 DECL_FRIENDLIST (typedecl));
   if (!uses_template_parms (type))
-    DECL_BEFRIENDING_CLASSES (decl) 
+    DECL_BEFRIENDING_CLASSES (decl)
       = tree_cons (NULL_TREE, type,
                   DECL_BEFRIENDING_CLASSES (decl));
 }
@@ -300,7 +305,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
                                                 tf_error);
              else
                friend_type
-                 = make_typename_type (ctype, name, tf_error);
+                 = make_typename_type (ctype, name, class_type, tf_error);
            }
          else
            {
@@ -314,7 +319,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
                {
                  error ("%qT is not a member class template of %qT",
                         name, ctype);
-                 cp_error_at ("%qD declared here", decl);
+                 error ("%q+D declared here", decl);
                  return;
                }
              if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
@@ -322,7 +327,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
                {
                  error ("%qT is not a nested class of %qT",
                         name, ctype);
-                 cp_error_at ("%qD declared here", decl);
+                 error ("%q+D declared here", decl);
                  return;
                }
 
@@ -361,7 +366,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
          if (friend_type == probe)
            {
              if (complain)
-               warning ("%qD is already a friend of %qT", probe, type);
+               warning (0, "%qD is already a friend of %qT", probe, type);
              break;
            }
        }
@@ -370,13 +375,13 @@ make_friend_class (tree type, tree friend_type, bool complain)
          if (same_type_p (probe, friend_type))
            {
              if (complain)
-               warning ("%qT is already a friend of %qT", probe, type);
+               warning (0, "%qT is already a friend of %qT", probe, type);
              break;
            }
        }
     }
-  
-  if (!classes) 
+
+  if (!classes)
     {
       maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
 
@@ -386,30 +391,26 @@ make_friend_class (tree type, tree friend_type, bool complain)
        friend_type = TREE_TYPE (friend_type);
       if (!uses_template_parms (type))
        CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
-         = tree_cons (NULL_TREE, type, 
-                      CLASSTYPE_BEFRIENDING_CLASSES (friend_type)); 
+         = tree_cons (NULL_TREE, type,
+                      CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
     }
 }
 
-/* Main friend processor. 
-
-   CTYPE is the class this friend belongs to.
-
-   DECLARATOR is the name of the friend.
-
-   DECL is the FUNCTION_DECL that the friend is.
-
-   FLAGS is just used for `grokclassfn'.
-
-   QUALS say what special qualifies should apply to the object
-   pointed to by `this'.  */
+/* Record DECL (a FUNCTION_DECL) as a friend of the
+   CURRENT_CLASS_TYPE.  If DECL is a member function, CTYPE is the
+   class of which it is a member, as named in the friend declaration.
+   DECLARATOR is the name of the friend.  FUNCDEF_FLAG is true if the
+   friend declaration is a definition of the function.  FLAGS is as
+   for grokclass fn.  */
 
 tree
 do_friend (tree ctype, tree declarator, tree decl,
-          tree attrlist, enum overload_flags flags, 
-          cp_cv_quals quals,
-          int funcdef_flag)
+          tree attrlist, enum overload_flags flags,
+          bool funcdef_flag)
 {
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+  gcc_assert (!ctype || IS_AGGR_TYPE (ctype));
+
   /* Every decl that gets here is a friend of something.  */
   DECL_FRIEND_P (decl) = 1;
 
@@ -420,8 +421,6 @@ do_friend (tree ctype, tree declarator, tree decl,
        declarator = DECL_NAME (get_first_fn (declarator));
     }
 
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-
   if (ctype)
     {
       /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
@@ -456,8 +455,7 @@ do_friend (tree ctype, tree declarator, tree decl,
       if (flags == NO_SPECIAL && declarator == cname)
        DECL_CONSTRUCTOR_P (decl) = 1;
 
-      /* This will set up DECL_ARGUMENTS for us.  */
-      grokclassfn (ctype, decl, flags, quals);
+      grokclassfn (ctype, decl, flags);
 
       if (friend_depth)
        {
@@ -480,10 +478,10 @@ do_friend (tree ctype, tree declarator, tree decl,
          else if (class_template_depth)
            /* We rely on tsubst_friend_function to check the
               validity of the declaration later.  */
-           decl = push_template_decl_real (decl, /*is_friend=*/1);
+           decl = push_template_decl_real (decl, /*is_friend=*/true);
          else
-           decl = check_classfn (ctype, decl, 
-                                 template_member_p 
+           decl = check_classfn (ctype, decl,
+                                 template_member_p
                                  ? current_template_parms
                                  : NULL_TREE);
 
@@ -527,37 +525,37 @@ do_friend (tree ctype, tree declarator, tree decl,
               general, such a declaration depends on template
               parameters.  Instead, we call pushdecl when the class
               is instantiated.  */
-           decl = push_template_decl_real (decl, /*is_friend=*/1); 
+           decl = push_template_decl_real (decl, /*is_friend=*/true);
          else if (current_function_decl)
            /* This must be a local class, so pushdecl will be ok, and
               insert an unqualified friend into the local scope
               (rather than the containing namespace scope, which the
               next choice will do).  */
-           decl = pushdecl (decl);
+           decl = pushdecl_maybe_friend (decl, /*is_friend=*/true);
          else
            {
              /* We can't use pushdecl, as we might be in a template
-                class specialization, and pushdecl will insert an
-                unqualified friend decl into the template parameter
-                scope, rather than the namespace containing it.  */
+                class specialization, and pushdecl will insert an
+                unqualified friend decl into the template parameter
+                scope, rather than the namespace containing it.  */
              tree ns = decl_namespace_context (decl);
-             
+
              push_nested_namespace (ns);
-             decl = pushdecl_namespace_level (decl);
+             decl = pushdecl_namespace_level (decl, /*is_friend=*/true);
              pop_nested_namespace (ns);
            }
 
          if (warn)
            {
              static int explained;
-             warning ("friend declaration %q#D declares a non-template "
-                       "function", decl);
+             warning (0, "friend declaration %q#D declares a non-template "
+                      "function", decl);
              if (! explained)
                {
-                 warning ("(if this is not what you intended, make sure "
-                           "the function template has already been declared "
-                           "and add <> after the function name here) "
-                           "-Wno-non-template-friend disables this warning");
+                 warning (0, "(if this is not what you intended, make sure "
+                          "the function template has already been declared "
+                          "and add <> after the function name here) "
+                          "-Wno-non-template-friend disables this warning");
                  explained = 1;
                }
            }
@@ -565,8 +563,8 @@ do_friend (tree ctype, tree declarator, tree decl,
 
       if (decl == error_mark_node)
        return error_mark_node;
-      
-      add_friend (current_class_type, 
+
+      add_friend (current_class_type,
                  is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
                  /*complain=*/true);
       DECL_FRIEND_P (decl) = 1;