/* 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,
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"
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;
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;
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;
}
bool funcdef_flag)
{
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- gcc_assert (!ctype || IS_AGGR_TYPE (ctype));
+ 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);
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
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
if (warn)
{
static int explained;
- warning (OPT_Wnon_template_friend, "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)
{
- inform ("(if this is not what you intended, make sure "
+ 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;
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;
}