diff options
Diffstat (limited to 'gcc/cp/friend.c')
-rw-r--r-- | gcc/cp/friend.c | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c deleted file mode 100644 index 6d7d9d54003..00000000000 --- a/gcc/cp/friend.c +++ /dev/null @@ -1,414 +0,0 @@ -/* Help friends in C++. - Copyright (C) 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "tree.h" -#include "rtl.h" -#include "cp-tree.h" -#include "flags.h" -#include "output.h" - -/* Friend data structures: - - Lists of friend functions come from TYPE_DECL nodes. Since all - aggregate types are automatically typedef'd, these nodes are guaranteed - to exist. - - The TREE_PURPOSE of a friend list is the name of the friend, - and its TREE_VALUE is another list. - - For each element of that list, either the TREE_VALUE or the TREE_PURPOSE - will be filled in, but not both. The TREE_VALUE of that list is an - individual function which is a friend. The TREE_PURPOSE of that list - indicates a type in which all functions by that name are friends. - - Lists of friend classes come from _TYPE nodes. Love that consistency - thang. */ - -int -is_friend (type, supplicant) - tree type, supplicant; -{ - int declp; - register tree list; - - if (supplicant == NULL_TREE || type == NULL_TREE) - return 0; - - declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd'); - - if (declp) - /* It's a function decl. */ - { - tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); - tree name = DECL_NAME (supplicant); - tree ctype; - - if (DECL_FUNCTION_MEMBER_P (supplicant)) - ctype = DECL_CLASS_CONTEXT (supplicant); - else - ctype = NULL_TREE; - - for (; list ; list = TREE_CHAIN (list)) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - for (; friends ; friends = TREE_CHAIN (friends)) - { - if (ctype == TREE_PURPOSE (friends)) - return 1; - if (comptypes (TREE_TYPE (supplicant), - TREE_TYPE (TREE_VALUE (friends)), 1)) - return 1; - } - break; - } - } - } - else - /* It's a type. */ - { - if (type == supplicant) - return 1; - - list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type))); - for (; list ; list = TREE_CHAIN (list)) - if (supplicant == TREE_VALUE (list)) - return 1; - } - - { - tree context; - - if (! declp) - { - /* Are we a nested or local class? If so, we aren't friends - with the CONTEXT. */ - if (IS_AGGR_TYPE (supplicant)) - context = NULL_TREE; - else - context = DECL_CONTEXT (TYPE_MAIN_DECL (supplicant)); - } - else if (DECL_FUNCTION_MEMBER_P (supplicant)) - context = DECL_CLASS_CONTEXT (supplicant); - else - context = NULL_TREE; - - if (context) - return is_friend (type, context); - } - - return 0; -} - -/* Add a new friend to the friends of the aggregate type TYPE. - DECL is the FUNCTION_DECL of the friend being added. */ - -static void -add_friend (type, decl) - tree type, decl; -{ - tree typedecl = TYPE_MAIN_DECL (type); - tree list = DECL_FRIENDLIST (typedecl); - tree name = DECL_NAME (decl); - - while (list) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - for (; friends ; friends = TREE_CHAIN (friends)) - { - if (decl == TREE_VALUE (friends)) - { - cp_warning ("`%D' is already a friend of class `%T'", - decl, type); - cp_warning_at ("previous friend declaration of `%D'", - TREE_VALUE (friends)); - return; - } - } - TREE_VALUE (list) = tree_cons (error_mark_node, decl, - TREE_VALUE (list)); - return; - } - list = TREE_CHAIN (list); - } - DECL_FRIENDLIST (typedecl) - = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), - DECL_FRIENDLIST (typedecl)); - if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) - { - tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); - TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; - if (parmtypes && TREE_CHAIN (parmtypes)) - { - tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes)); - if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl)) - TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1; - } - } -} - -/* Declare that every member function NAME in FRIEND_TYPE - (which may be NULL_TREE) is a friend of type TYPE. */ - -static void -add_friends (type, name, friend_type) - tree type, name, friend_type; -{ - tree typedecl = TYPE_MAIN_DECL (type); - tree list = DECL_FRIENDLIST (typedecl); - - while (list) - { - if (name == TREE_PURPOSE (list)) - { - tree friends = TREE_VALUE (list); - while (friends && TREE_PURPOSE (friends) != friend_type) - friends = TREE_CHAIN (friends); - if (friends) - if (friend_type) - warning ("method `%s::%s' is already a friend of class", - TYPE_NAME_STRING (friend_type), - IDENTIFIER_POINTER (name)); - else - warning ("function `%s' is already a friend of class `%s'", - IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (DECL_NAME (typedecl))); - else - TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE, - TREE_VALUE (list)); - return; - } - list = TREE_CHAIN (list); - } - DECL_FRIENDLIST (typedecl) = - tree_cons (name, - build_tree_list (friend_type, NULL_TREE), - DECL_FRIENDLIST (typedecl)); - if (! strncmp (IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]), - strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR])))) - { - TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; - sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists"); - } -} - -/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already - been defined, we make all of its member functions friends of - TYPE. If not, we make it a pending friend, which can later be added - when its definition is seen. If a type is defined, then its TYPE_DECL's - DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend - classes that are not defined. If a type has not yet been defined, - then the DECL_WAITING_FRIENDS contains a list of types - waiting to make it their friend. Note that these two can both - be in use at the same time! */ - -void -make_friend_class (type, friend_type) - tree type, friend_type; -{ - tree classes; - - if (IS_SIGNATURE (type)) - { - error ("`friend' declaration in signature definition"); - return; - } - if (IS_SIGNATURE (friend_type)) - { - error ("signature type `%s' declared `friend'", - IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); - return; - } - if (type == friend_type) - { - pedwarn ("class `%s' is implicitly friends with itself", - TYPE_NAME_STRING (type)); - return; - } - - GNU_xref_hier (TYPE_NAME_STRING (type), - TYPE_NAME_STRING (friend_type), 0, 0, 1); - - classes = CLASSTYPE_FRIEND_CLASSES (type); - while (classes && TREE_VALUE (classes) != friend_type) - classes = TREE_CHAIN (classes); - if (classes) - warning ("class `%s' is already friends with class `%s'", - TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); - else - { - CLASSTYPE_FRIEND_CLASSES (type) - = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); - } -} - -/* Main friend processor. This is large, and for modularity purposes, - has been removed from grokdeclarator. It returns `void_type_node' - to indicate that something happened, though a FIELD_DECL is - not returned. - - CTYPE is the class this friend belongs to. - - DECLARATOR is the name of the friend. - - DECL is the FUNCTION_DECL that the friend is. - - In case we are parsing a friend which is part of an inline - definition, we will need to store PARM_DECL chain that comes - with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL. - - FLAGS is just used for `grokclassfn'. - - QUALS say what special qualifies should apply to the object - pointed to by `this'. */ - -tree -do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) - tree ctype, declarator, decl, parmdecls; - enum overload_flags flags; - tree quals; - int funcdef_flag; -{ - /* Every decl that gets here is a friend of something. */ - DECL_FRIEND_P (decl) = 1; - - if (ctype) - { - tree cname = TYPE_NAME (ctype); - if (TREE_CODE (cname) == TYPE_DECL) - cname = DECL_NAME (cname); - - /* A method friend. */ - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (flags == NO_SPECIAL && ctype && declarator == cname) - DECL_CONSTRUCTOR_P (decl) = 1; - - /* This will set up DECL_ARGUMENTS for us. */ - grokclassfn (ctype, cname, decl, flags, quals); - if (TYPE_SIZE (ctype) != 0) - decl = check_classfn (ctype, decl); - - if (TREE_TYPE (decl) != error_mark_node) - { - if (TYPE_SIZE (ctype)) - add_friend (current_class_type, decl); - else - { - cp_error ("member `%D' declared as friend before type `%T' defined", - decl, ctype); - } - } - } - else - { - /* Possibly a bunch of method friends. */ - - /* Get the class they belong to. */ - tree ctype = IDENTIFIER_TYPE_VALUE (cname); - tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0); - - if (fields) - add_friends (current_class_type, declarator, ctype); - else - error ("method `%s' is not a member of class `%s'", - IDENTIFIER_POINTER (declarator), - IDENTIFIER_POINTER (cname)); - decl = void_type_node; - } - } - else if (TREE_CODE (decl) == FUNCTION_DECL - && ((IDENTIFIER_LENGTH (declarator) == 4 - && IDENTIFIER_POINTER (declarator)[0] == 'm' - && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) - || (IDENTIFIER_LENGTH (declarator) > 10 - && IDENTIFIER_POINTER (declarator)[0] == '_' - && IDENTIFIER_POINTER (declarator)[1] == '_' - && strncmp (IDENTIFIER_POINTER (declarator)+2, - "builtin_", 8) == 0))) - { - /* raw "main", and builtin functions never gets overloaded, - but they can become friends. */ - add_friend (current_class_type, decl); - DECL_FRIEND_P (decl) = 1; - decl = void_type_node; - } - /* A global friend. - @@ or possibly a friend from a base class ?!? */ - else if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* Friends must all go through the overload machinery, - even though they may not technically be overloaded. - - Note that because classes all wind up being top-level - in their scope, their friend wind up in top-level scope as well. */ - DECL_ASSEMBLER_NAME (decl) - = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)), - TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); - DECL_ARGUMENTS (decl) = parmdecls; - if (funcdef_flag) - DECL_CLASS_CONTEXT (decl) = current_class_type; - - /* We can call pushdecl here, because the TREE_CHAIN of this - FUNCTION_DECL is not needed for other purposes. */ - decl = pushdecl (decl); - - make_decl_rtl (decl, NULL_PTR, 1); - add_friend (current_class_type, decl); - - DECL_FRIEND_P (decl) = 1; - } - else - { - /* @@ Should be able to ingest later definitions of this function - before use. */ - tree decl = lookup_name_nonclass (declarator); - if (decl == NULL_TREE) - { - warning ("implicitly declaring `%s' as struct", - IDENTIFIER_POINTER (declarator)); - decl = xref_tag (record_type_node, declarator, NULL_TREE, 1); - decl = TYPE_MAIN_DECL (decl); - } - - /* Allow abbreviated declarations of overloaded functions, - but not if those functions are really class names. */ - if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl))) - { - warning ("`friend %s' archaic, use `friend class %s' instead", - IDENTIFIER_POINTER (declarator), - IDENTIFIER_POINTER (declarator)); - decl = TREE_TYPE (TREE_PURPOSE (decl)); - } - - if (TREE_CODE (decl) == TREE_LIST) - add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE); - else - make_friend_class (current_class_type, TREE_TYPE (decl)); - decl = void_type_node; - } - return decl; -} |