OSDN Git Service

* call.c (struct z_candidate): Add explicit_targs field.
[pf3gnuchains/gcc-fork.git] / gcc / cp / friend.c
index c71b90f..03748fe 100644 (file)
@@ -1,12 +1,12 @@
 /* Help friends in C++.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2007, 2008  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -60,15 +59,15 @@ is_friend (tree type, tree supplicant)
              tree friends = FRIEND_DECLS (list);
              for (; friends ; friends = TREE_CHAIN (friends))
                {
-                 tree friend = TREE_VALUE (friends);
+                 tree this_friend = TREE_VALUE (friends);
 
-                 if (friend == NULL_TREE)
+                 if (this_friend == NULL_TREE)
                    continue;
 
-                 if (supplicant == friend)
+                 if (supplicant == this_friend)
                    return 1;
 
-                 if (is_specialization_of_friend (supplicant, friend))
+                 if (is_specialization_of_friend (supplicant, this_friend))
                    return 1;
                }
              break;
@@ -78,13 +77,8 @@ 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))
@@ -98,13 +92,23 @@ is_friend (tree type, tree supplicant)
        }
     }
 
-  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)
@@ -166,7 +170,7 @@ add_friend (tree type, tree decl, bool complain)
 
   ctx = DECL_CONTEXT (decl);
   if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
-    perform_or_defer_access_check (TYPE_BINFO (ctx), decl);
+    perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl);
 
   maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
 
@@ -223,7 +227,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
   int class_template_depth = template_class_depth (type);
   int friend_depth = processing_template_decl - class_template_depth;
 
-  if (! IS_AGGR_TYPE (friend_type))
+  if (! MAYBE_CLASS_TYPE_P (friend_type))
     {
       error ("invalid type %qT declared %<friend%>", friend_type);
       return;
@@ -249,7 +253,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
   else if (same_type_p (type, friend_type))
     {
       if (complain)
-       pedwarn ("class %qT is implicitly friends with itself",
+       warning (0, "class %qT is implicitly friends with itself",
                 type);
       return;
     }
@@ -391,28 +395,31 @@ make_friend_class (tree type, tree friend_type, bool complain)
     }
 }
 
-/* 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)
+          bool funcdef_flag)
 {
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+  gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype));
+
   /* Every decl that gets here is a friend of something.  */
   DECL_FRIEND_P (decl) = 1;
 
+  /* Unfortunately, we have to handle attributes here.  Normally we would
+     handle them in start_decl_1, but since this is a friend decl start_decl_1
+     never gets to see it.  */
+
+  /* Set attributes here so if duplicate decl, will have proper attributes.  */
+  cplus_decl_attributes (&decl, attrlist, 0);
+
   if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
     {
       declarator = TREE_OPERAND (declarator, 0);
@@ -420,8 +427,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 +461,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)
        {
@@ -471,7 +475,7 @@ do_friend (tree ctype, tree declarator, tree decl,
         the process of being defined.  */
       if (class_template_depth
          || COMPLETE_TYPE_P (ctype)
-         || TYPE_BEING_DEFINED (ctype))
+         || (CLASS_TYPE_P (ctype) && TYPE_BEING_DEFINED (ctype)))
        {
          if (DECL_TEMPLATE_INFO (decl))
            /* DECL is a template specialization.  No need to
@@ -529,11 +533,25 @@ do_friend (tree ctype, tree declarator, tree decl,
               is instantiated.  */
            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_maybe_friend (decl, /*is_friend=*/true);
+           {
+             /* This must be a local class.  11.5p11:
+
+                If a friend declaration appears in a local class (9.8) and
+                the name specified is an unqualified name, a prior
+                declaration is looked up without considering scopes that
+                are outside the innermost enclosing non-class scope. For a
+                friend function declaration, if there is no prior
+                declaration, the program is ill-formed.  */
+             tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl));
+             if (t)
+               decl = pushdecl_maybe_friend (decl, /*is_friend=*/true);
+             else
+               {
+                 error ("friend declaration %qD in local class without "
+                        "prior declaration", decl);
+                 return error_mark_node;
+               }
+           }
          else
            {
              /* We can't use pushdecl, as we might be in a template
@@ -550,14 +568,15 @@ do_friend (tree ctype, tree declarator, tree decl,
          if (warn)
            {
              static int explained;
-             warning (0, "friend declaration %q#D declares a non-template "
-                      "function", decl);
-             if (! explained)
+             bool warned;
+
+             warned = warning (OPT_Wnon_template_friend, "friend declaration "
+                               "%q#D declares a non-template function", decl);
+             if (! explained && warned)
                {
-                 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");
+                 inform (input_location, "(if this is not what you intended, make sure "
+                         "the function template has already been declared "
+                         "and add <> after the function name here) ");
                  explained = 1;
                }
            }
@@ -572,12 +591,5 @@ do_friend (tree ctype, tree declarator, tree decl,
       DECL_FRIEND_P (decl) = 1;
     }
 
-  /* Unfortunately, we have to handle attributes here.  Normally we would
-     handle them in start_decl_1, but since this is a friend decl start_decl_1
-     never gets to see it.  */
-
-  /* Set attributes here so if duplicate decl, will have proper attributes.  */
-  cplus_decl_attributes (&decl, attrlist, 0);
-
   return decl;
 }