friend.c revision 50397
150397Sobrien/* Help friends in C++.
250397Sobrien   Copyright (C) 1997 Free Software Foundation, Inc.
350397Sobrien
450397SobrienThis file is part of GNU CC.
550397Sobrien
650397SobrienGNU CC is free software; you can redistribute it and/or modify
750397Sobrienit under the terms of the GNU General Public License as published by
850397Sobrienthe Free Software Foundation; either version 2, or (at your option)
950397Sobrienany later version.
1050397Sobrien
1150397SobrienGNU CC is distributed in the hope that it will be useful,
1250397Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1350397SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1450397SobrienGNU General Public License for more details.
1550397Sobrien
1650397SobrienYou should have received a copy of the GNU General Public License
1750397Sobrienalong with GNU CC; see the file COPYING.  If not, write to
1850397Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330,
1950397SobrienBoston, MA 02111-1307, USA.  */
2050397Sobrien
2150397Sobrien#include "config.h"
2250397Sobrien#include "system.h"
2350397Sobrien#include "tree.h"
2450397Sobrien#include "rtl.h"
2550397Sobrien#include "cp-tree.h"
2650397Sobrien#include "flags.h"
2750397Sobrien#include "output.h"
2850397Sobrien#include "toplev.h"
2950397Sobrien
3050397Sobrienstatic void add_friend PROTO((tree, tree));
3150397Sobrienstatic void add_friends PROTO((tree, tree, tree));
3250397Sobrien
3350397Sobrien/* Friend data structures are described in cp-tree.h.  */
3450397Sobrien
3550397Sobrienint
3650397Sobrienis_friend (type, supplicant)
3750397Sobrien     tree type, supplicant;
3850397Sobrien{
3950397Sobrien  int declp;
4050397Sobrien  register tree list;
4150397Sobrien  tree context;
4250397Sobrien
4350397Sobrien  if (supplicant == NULL_TREE || type == NULL_TREE)
4450397Sobrien    return 0;
4550397Sobrien
4650397Sobrien  declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
4750397Sobrien
4850397Sobrien  if (declp)
4950397Sobrien    /* It's a function decl.  */
5050397Sobrien    {
5150397Sobrien      tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
5250397Sobrien      tree name = DECL_NAME (supplicant);
5350397Sobrien      tree ctype;
5450397Sobrien
5550397Sobrien      if (DECL_FUNCTION_MEMBER_P (supplicant))
5650397Sobrien	ctype = DECL_CLASS_CONTEXT (supplicant);
5750397Sobrien      else
5850397Sobrien	ctype = NULL_TREE;
5950397Sobrien
6050397Sobrien      for (; list ; list = TREE_CHAIN (list))
6150397Sobrien	{
6250397Sobrien	  if (name == TREE_PURPOSE (list))
6350397Sobrien	    {
6450397Sobrien	      tree friends = TREE_VALUE (list);
6550397Sobrien	      for (; friends ; friends = TREE_CHAIN (friends))
6650397Sobrien		{
6750397Sobrien		  if (comptypes (ctype, TREE_PURPOSE (friends), 1))
6850397Sobrien		    return 1;
6950397Sobrien
7050397Sobrien		  if (TREE_VALUE (friends) == NULL_TREE)
7150397Sobrien		    continue;
7250397Sobrien
7350397Sobrien		  if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
7450397Sobrien		    {
7550397Sobrien		      if (is_specialization_of (supplicant,
7650397Sobrien						TREE_VALUE (friends)))
7750397Sobrien			return 1;
7850397Sobrien
7950397Sobrien		      continue;
8050397Sobrien		    }
8150397Sobrien
8250397Sobrien		  /* FIXME: The use of comptypes here is bogus, since
8350397Sobrien		     two specializations of a template with non-type
8450397Sobrien		     parameters may have the same type, but be
8550397Sobrien		     different.  */
8650397Sobrien		  if (comptypes (TREE_TYPE (supplicant),
8750397Sobrien				 TREE_TYPE (TREE_VALUE (friends)), 1))
8850397Sobrien		    return 1;
8950397Sobrien		}
9050397Sobrien	      break;
9150397Sobrien	    }
9250397Sobrien	}
9350397Sobrien    }
9450397Sobrien  else
9550397Sobrien    /* It's a type.  */
9650397Sobrien    {
9750397Sobrien      if (type == supplicant)
9850397Sobrien	return 1;
9950397Sobrien
10050397Sobrien      list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
10150397Sobrien      for (; list ; list = TREE_CHAIN (list))
10250397Sobrien	{
10350397Sobrien	  tree t = TREE_VALUE (list);
10450397Sobrien
10550397Sobrien	  if (TREE_CODE (t) == TEMPLATE_DECL ?
10650397Sobrien	      is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
10750397Sobrien	      comptypes (supplicant, t, 1))
10850397Sobrien	    return 1;
10950397Sobrien	}
11050397Sobrien    }
11150397Sobrien
11250397Sobrien  if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
11350397Sobrien    context = DECL_CLASS_CONTEXT (supplicant);
11450397Sobrien  else if (! declp)
11550397Sobrien    /* Local classes have the same access as the enclosing function.  */
11650397Sobrien    context = hack_decl_function_context (TYPE_MAIN_DECL (supplicant));
11750397Sobrien  else
11850397Sobrien    context = NULL_TREE;
11950397Sobrien
12050397Sobrien  /* A namespace is not friend to anybody. */
12150397Sobrien  if (context && TREE_CODE (context) == NAMESPACE_DECL)
12250397Sobrien    context = NULL_TREE;
12350397Sobrien
12450397Sobrien  if (context)
12550397Sobrien    return is_friend (type, context);
12650397Sobrien
12750397Sobrien  return 0;
12850397Sobrien}
12950397Sobrien
13050397Sobrien/* Add a new friend to the friends of the aggregate type TYPE.
13150397Sobrien   DECL is the FUNCTION_DECL of the friend being added.  */
13250397Sobrien
13350397Sobrienstatic void
13450397Sobrienadd_friend (type, decl)
13550397Sobrien     tree type, decl;
13650397Sobrien{
13750397Sobrien  tree typedecl = TYPE_MAIN_DECL (type);
13850397Sobrien  tree list = DECL_FRIENDLIST (typedecl);
13950397Sobrien  tree name = DECL_NAME (decl);
14050397Sobrien
14150397Sobrien  while (list)
14250397Sobrien    {
14350397Sobrien      if (name == TREE_PURPOSE (list))
14450397Sobrien	{
14550397Sobrien	  tree friends = TREE_VALUE (list);
14650397Sobrien	  for (; friends ; friends = TREE_CHAIN (friends))
14750397Sobrien	    {
14850397Sobrien	      if (decl == TREE_VALUE (friends))
14950397Sobrien		{
15050397Sobrien		  cp_warning ("`%D' is already a friend of class `%T'",
15150397Sobrien			      decl, type);
15250397Sobrien		  cp_warning_at ("previous friend declaration of `%D'",
15350397Sobrien				 TREE_VALUE (friends));
15450397Sobrien		  return;
15550397Sobrien		}
15650397Sobrien	    }
15750397Sobrien	  TREE_VALUE (list) = tree_cons (error_mark_node, decl,
15850397Sobrien					 TREE_VALUE (list));
15950397Sobrien	  return;
16050397Sobrien	}
16150397Sobrien      list = TREE_CHAIN (list);
16250397Sobrien    }
16350397Sobrien  DECL_FRIENDLIST (typedecl)
16450397Sobrien    = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
16550397Sobrien		 DECL_FRIENDLIST (typedecl));
16650397Sobrien  if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
16750397Sobrien    {
16850397Sobrien      tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
16950397Sobrien      TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
17050397Sobrien      if (parmtypes && TREE_CHAIN (parmtypes))
17150397Sobrien	{
17250397Sobrien	  tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
17350397Sobrien	  if (TREE_CODE (parmtype) == REFERENCE_TYPE
17450397Sobrien	      && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
17550397Sobrien	    TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
17650397Sobrien	}
17750397Sobrien    }
17850397Sobrien}
17950397Sobrien
18050397Sobrien/* Declare that every member function NAME in FRIEND_TYPE
18150397Sobrien   (which may be NULL_TREE) is a friend of type TYPE.  */
18250397Sobrien
18350397Sobrienstatic void
18450397Sobrienadd_friends (type, name, friend_type)
18550397Sobrien     tree type, name, friend_type;
18650397Sobrien{
18750397Sobrien  tree typedecl = TYPE_MAIN_DECL (type);
18850397Sobrien  tree list = DECL_FRIENDLIST (typedecl);
18950397Sobrien
19050397Sobrien  while (list)
19150397Sobrien    {
19250397Sobrien      if (name == TREE_PURPOSE (list))
19350397Sobrien	{
19450397Sobrien	  tree friends = TREE_VALUE (list);
19550397Sobrien	  while (friends && TREE_PURPOSE (friends) != friend_type)
19650397Sobrien	    friends = TREE_CHAIN (friends);
19750397Sobrien	  if (friends)
19850397Sobrien	    {
19950397Sobrien	      if (friend_type)
20050397Sobrien		warning ("method `%s::%s' is already a friend of class",
20150397Sobrien			 TYPE_NAME_STRING (friend_type),
20250397Sobrien			 IDENTIFIER_POINTER (name));
20350397Sobrien	      else
20450397Sobrien		warning ("function `%s' is already a friend of class `%s'",
20550397Sobrien			 IDENTIFIER_POINTER (name),
20650397Sobrien			 IDENTIFIER_POINTER (DECL_NAME (typedecl)));
20750397Sobrien	    }
20850397Sobrien	  else
20950397Sobrien	    TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
21050397Sobrien					   TREE_VALUE (list));
21150397Sobrien	  return;
21250397Sobrien	}
21350397Sobrien      list = TREE_CHAIN (list);
21450397Sobrien    }
21550397Sobrien  DECL_FRIENDLIST (typedecl)
21650397Sobrien    = tree_cons (name,
21750397Sobrien		 build_tree_list (friend_type, NULL_TREE),
21850397Sobrien		 DECL_FRIENDLIST (typedecl));
21950397Sobrien  if (! strncmp (IDENTIFIER_POINTER (name),
22050397Sobrien		 IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
22150397Sobrien		 strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
22250397Sobrien    {
22350397Sobrien      TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
22450397Sobrien      sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
22550397Sobrien    }
22650397Sobrien}
22750397Sobrien
22850397Sobrien/* Make FRIEND_TYPE a friend class to TYPE.  If FRIEND_TYPE has already
22950397Sobrien   been defined, we make all of its member functions friends of
23050397Sobrien   TYPE.  If not, we make it a pending friend, which can later be added
23150397Sobrien   when its definition is seen.  If a type is defined, then its TYPE_DECL's
23250397Sobrien   DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
23350397Sobrien   classes that are not defined.  If a type has not yet been defined,
23450397Sobrien   then the DECL_WAITING_FRIENDS contains a list of types
23550397Sobrien   waiting to make it their friend.  Note that these two can both
23650397Sobrien   be in use at the same time!  */
23750397Sobrien
23850397Sobrienvoid
23950397Sobrienmake_friend_class (type, friend_type)
24050397Sobrien     tree type, friend_type;
24150397Sobrien{
24250397Sobrien  tree classes;
24350397Sobrien  int is_template_friend;
24450397Sobrien
24550397Sobrien  if (IS_SIGNATURE (type))
24650397Sobrien    {
24750397Sobrien      error ("`friend' declaration in signature definition");
24850397Sobrien      return;
24950397Sobrien    }
25050397Sobrien  if (IS_SIGNATURE (friend_type))
25150397Sobrien    {
25250397Sobrien      error ("signature type `%s' declared `friend'",
25350397Sobrien	     IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
25450397Sobrien      return;
25550397Sobrien    }
25650397Sobrien  if (processing_template_decl > template_class_depth (type))
25750397Sobrien    /* If the TYPE is a template then it makes sense for it to be
25850397Sobrien       friends with itself; this means that each instantiation is
25950397Sobrien       friends with all other instantiations.  */
26050397Sobrien    is_template_friend = 1;
26150397Sobrien  else if (comptypes (type, friend_type, 1))
26250397Sobrien    {
26350397Sobrien      pedwarn ("class `%s' is implicitly friends with itself",
26450397Sobrien	       TYPE_NAME_STRING (type));
26550397Sobrien      return;
26650397Sobrien    }
26750397Sobrien  else
26850397Sobrien    is_template_friend = 0;
26950397Sobrien
27050397Sobrien  GNU_xref_hier (type, friend_type, 0, 0, 1);
27150397Sobrien
27250397Sobrien  if (is_template_friend)
27350397Sobrien    friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
27450397Sobrien
27550397Sobrien  classes = CLASSTYPE_FRIEND_CLASSES (type);
27650397Sobrien  while (classes
27750397Sobrien	 /* Stop if we find the same type on the list.  */
27850397Sobrien	 && !(TREE_CODE (TREE_VALUE (classes)) == TEMPLATE_DECL ?
27950397Sobrien	      friend_type == TREE_VALUE (classes) :
28050397Sobrien	      comptypes (TREE_VALUE (classes), friend_type, 1)))
28150397Sobrien    classes = TREE_CHAIN (classes);
28250397Sobrien  if (classes)
28350397Sobrien    cp_warning ("`%T' is already a friend of `%T'",
28450397Sobrien		TREE_VALUE (classes), type);
28550397Sobrien  else
28650397Sobrien    {
28750397Sobrien      CLASSTYPE_FRIEND_CLASSES (type)
28850397Sobrien	= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
28950397Sobrien    }
29050397Sobrien}
29150397Sobrien
29250397Sobrien/* Main friend processor.  This is large, and for modularity purposes,
29350397Sobrien   has been removed from grokdeclarator.  It returns `void_type_node'
29450397Sobrien   to indicate that something happened, though a FIELD_DECL is
29550397Sobrien   not returned.
29650397Sobrien
29750397Sobrien   CTYPE is the class this friend belongs to.
29850397Sobrien
29950397Sobrien   DECLARATOR is the name of the friend.
30050397Sobrien
30150397Sobrien   DECL is the FUNCTION_DECL that the friend is.
30250397Sobrien
30350397Sobrien   In case we are parsing a friend which is part of an inline
30450397Sobrien   definition, we will need to store PARM_DECL chain that comes
30550397Sobrien   with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
30650397Sobrien
30750397Sobrien   FLAGS is just used for `grokclassfn'.
30850397Sobrien
30950397Sobrien   QUALS say what special qualifies should apply to the object
31050397Sobrien   pointed to by `this'.  */
31150397Sobrien
31250397Sobrientree
31350397Sobriendo_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
31450397Sobrien     tree ctype, declarator, decl, parmdecls;
31550397Sobrien     enum overload_flags flags;
31650397Sobrien     tree quals;
31750397Sobrien     int funcdef_flag;
31850397Sobrien{
31950397Sobrien  int is_friend_template = 0;
32050397Sobrien
32150397Sobrien  /* Every decl that gets here is a friend of something.  */
32250397Sobrien  DECL_FRIEND_P (decl) = 1;
32350397Sobrien
32450397Sobrien  if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
32550397Sobrien    {
32650397Sobrien      declarator = TREE_OPERAND (declarator, 0);
32750397Sobrien      if (TREE_CODE (declarator) == LOOKUP_EXPR)
32850397Sobrien	declarator = TREE_OPERAND (declarator, 0);
32950397Sobrien      if (is_overloaded_fn (declarator))
33050397Sobrien	declarator = DECL_NAME (get_first_fn (declarator));
33150397Sobrien    }
33250397Sobrien
33350397Sobrien  if (TREE_CODE (decl) == FUNCTION_DECL)
33450397Sobrien    is_friend_template = processing_template_decl >
33550397Sobrien      template_class_depth (current_class_type);
33650397Sobrien
33750397Sobrien  if (ctype)
33850397Sobrien    {
33950397Sobrien      tree cname = TYPE_NAME (ctype);
34050397Sobrien      if (TREE_CODE (cname) == TYPE_DECL)
34150397Sobrien	cname = DECL_NAME (cname);
34250397Sobrien
34350397Sobrien      /* A method friend.  */
34450397Sobrien      if (TREE_CODE (decl) == FUNCTION_DECL)
34550397Sobrien	{
34650397Sobrien	  if (flags == NO_SPECIAL && ctype && declarator == cname)
34750397Sobrien	    DECL_CONSTRUCTOR_P (decl) = 1;
34850397Sobrien
34950397Sobrien	  /* This will set up DECL_ARGUMENTS for us.  */
35050397Sobrien	  grokclassfn (ctype, cname, decl, flags, quals);
35150397Sobrien
35250397Sobrien	  if (is_friend_template)
35350397Sobrien	    decl = DECL_TI_TEMPLATE (push_template_decl (decl));
35450397Sobrien
35550397Sobrien	  if (TYPE_SIZE (ctype) != 0 && template_class_depth (ctype) == 0)
35650397Sobrien	    decl = check_classfn (ctype, decl);
35750397Sobrien
35850397Sobrien	  /* TYPE_BEING_DEFINED is a hack for nested classes having
35950397Sobrien             member functions of the enclosing class as friends. Will
36050397Sobrien             go away as parsing of classes gets rewritten. */
36150397Sobrien	  if (TREE_TYPE (decl) != error_mark_node)
36250397Sobrien	    {
36350397Sobrien	      if (TYPE_BEING_DEFINED (ctype) ||
36450397Sobrien		  TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
36550397Sobrien		add_friend (current_class_type, decl);
36650397Sobrien	      else
36750397Sobrien		cp_error ("member `%D' declared as friend before type `%T' defined",
36850397Sobrien			  decl, ctype);
36950397Sobrien	    }
37050397Sobrien	}
37150397Sobrien      else
37250397Sobrien	{
37350397Sobrien	  /* Possibly a bunch of method friends.  */
37450397Sobrien
37550397Sobrien	  /* Get the class they belong to.  */
37650397Sobrien	  tree ctype = IDENTIFIER_TYPE_VALUE (cname);
37750397Sobrien	  tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
37850397Sobrien
37950397Sobrien	  if (fields)
38050397Sobrien	    add_friends (current_class_type, declarator, ctype);
38150397Sobrien	  else
38250397Sobrien	    cp_error ("method `%D' is not a member of class `%T'",
38350397Sobrien		      declarator, ctype);
38450397Sobrien	  decl = void_type_node;
38550397Sobrien	}
38650397Sobrien    }
38750397Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL
38850397Sobrien	   && (MAIN_NAME_P (declarator)
38950397Sobrien	       || (IDENTIFIER_LENGTH (declarator) > 10
39050397Sobrien		   && IDENTIFIER_POINTER (declarator)[0] == '_'
39150397Sobrien		   && IDENTIFIER_POINTER (declarator)[1] == '_'
39250397Sobrien		   && strncmp (IDENTIFIER_POINTER (declarator)+2,
39350397Sobrien			       "builtin_", 8) == 0)))
39450397Sobrien    {
39550397Sobrien      /* raw "main", and builtin functions never gets overloaded,
39650397Sobrien	 but they can become friends.  */
39750397Sobrien      add_friend (current_class_type, decl);
39850397Sobrien      DECL_FRIEND_P (decl) = 1;
39950397Sobrien      decl = void_type_node;
40050397Sobrien    }
40150397Sobrien  /* A global friend.
40250397Sobrien     @@ or possibly a friend from a base class ?!?  */
40350397Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL)
40450397Sobrien    {
40550397Sobrien      /* Friends must all go through the overload machinery,
40650397Sobrien	 even though they may not technically be overloaded.
40750397Sobrien
40850397Sobrien	 Note that because classes all wind up being top-level
40950397Sobrien	 in their scope, their friend wind up in top-level scope as well.  */
41050397Sobrien      DECL_ASSEMBLER_NAME (decl)
41150397Sobrien	= build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
41250397Sobrien			       TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
41350397Sobrien      DECL_ARGUMENTS (decl) = parmdecls;
41450397Sobrien      if (funcdef_flag)
41550397Sobrien	DECL_CLASS_CONTEXT (decl) = current_class_type;
41650397Sobrien
41750397Sobrien      if (! DECL_USE_TEMPLATE (decl))
41850397Sobrien	{
41950397Sobrien	  /* We can call pushdecl here, because the TREE_CHAIN of this
42050397Sobrien	     FUNCTION_DECL is not needed for other purposes.  Don't do this
42150397Sobrien	     for a template instantiation.  */
42250397Sobrien	  if (!is_friend_template)
42350397Sobrien	    {
42450397Sobrien	      /* However, we don't call pushdecl() for a friend
42550397Sobrien		 function of a template class, since in general,
42650397Sobrien		 such a declaration depends on template
42750397Sobrien		 parameters.  Instead, we call pushdecl when the
42850397Sobrien		 class is instantiated.  */
42950397Sobrien	      if (template_class_depth (current_class_type) == 0)
43050397Sobrien		decl = pushdecl (decl);
43150397Sobrien	    }
43250397Sobrien	  else
43350397Sobrien	    decl = push_template_decl (decl);
43450397Sobrien
43550397Sobrien	  if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
43650397Sobrien	      && current_template_parms && uses_template_parms (decl))
43750397Sobrien	    {
43850397Sobrien	      static int explained;
43950397Sobrien	      cp_warning ("friend declaration `%#D'", decl);
44050397Sobrien	      warning ("  declares a non-template function");
44150397Sobrien	      if (! explained)
44250397Sobrien		{
44350397Sobrien		  warning ("  (if this is not what you intended, make sure");
44450397Sobrien		  warning ("  the function template has already been declared,");
44550397Sobrien		  warning ("  and add <> after the function name here)");
44650397Sobrien		  explained = 1;
44750397Sobrien		}
44850397Sobrien	    }
44950397Sobrien	}
45050397Sobrien
45150397Sobrien      make_decl_rtl (decl, NULL_PTR, 1);
45250397Sobrien      add_friend (current_class_type,
45350397Sobrien		  is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
45450397Sobrien      DECL_FRIEND_P (decl) = 1;
45550397Sobrien    }
45650397Sobrien  else
45750397Sobrien    {
45850397Sobrien      /* @@ Should be able to ingest later definitions of this function
45950397Sobrien	 before use.  */
46050397Sobrien      tree decl = lookup_name_nonclass (declarator);
46150397Sobrien      if (decl == NULL_TREE)
46250397Sobrien	{
46350397Sobrien	  cp_warning ("implicitly declaring `%T' as struct", declarator);
46450397Sobrien	  decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
46550397Sobrien	  decl = TYPE_MAIN_DECL (decl);
46650397Sobrien	}
46750397Sobrien
46850397Sobrien      /* Allow abbreviated declarations of overloaded functions,
46950397Sobrien	 but not if those functions are really class names.  */
47050397Sobrien      if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
47150397Sobrien	{
47250397Sobrien	  cp_warning ("`friend %T' archaic, use `friend class %T' instead",
47350397Sobrien		      declarator, declarator);
47450397Sobrien	  decl = TREE_TYPE (TREE_PURPOSE (decl));
47550397Sobrien	}
47650397Sobrien
47750397Sobrien      if (TREE_CODE (decl) == TREE_LIST)
47850397Sobrien	add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
47950397Sobrien      else
48050397Sobrien	make_friend_class (current_class_type, TREE_TYPE (decl));
48150397Sobrien      decl = void_type_node;
48250397Sobrien    }
48350397Sobrien  return decl;
48450397Sobrien}
485