123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- /* Help friends in C++.
- Copyright (C) 1997-2015 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 3, or (at your option)
- any later version.
- GCC 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 GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tm.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "cp-tree.h"
- #include "flags.h"
- /* Friend data structures are described in cp-tree.h. */
- /* Returns nonzero if SUPPLICANT is a friend of TYPE. */
- int
- is_friend (tree type, tree supplicant)
- {
- int declp;
- tree list;
- tree context;
- if (supplicant == NULL_TREE || type == NULL_TREE)
- return 0;
- declp = DECL_P (supplicant);
- if (declp)
- /* It's a function decl. */
- {
- tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
- tree name = DECL_NAME (supplicant);
- for (; list ; list = TREE_CHAIN (list))
- {
- if (name == FRIEND_NAME (list))
- {
- tree friends = FRIEND_DECLS (list);
- for (; friends ; friends = TREE_CHAIN (friends))
- {
- tree this_friend = TREE_VALUE (friends);
- if (this_friend == NULL_TREE)
- continue;
- if (supplicant == this_friend)
- return 1;
- if (is_specialization_of_friend (supplicant, this_friend))
- return 1;
- }
- break;
- }
- }
- }
- else
- /* It's a type. */
- {
- 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 ?
- is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) :
- same_type_p (supplicant, t))
- return 1;
- }
- }
- if (declp)
- {
- if (DECL_FUNCTION_MEMBER_P (supplicant))
- context = DECL_CONTEXT (supplicant);
- else
- context = NULL_TREE;
- }
- else
- {
- 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)
- 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.
- If COMPLAIN is true, warning about duplicate friend is issued.
- We want to have this diagnostics during parsing but not
- when a template is being instantiated. */
- void
- add_friend (tree type, tree decl, bool complain)
- {
- tree typedecl;
- tree list;
- tree name;
- tree ctx;
- if (decl == error_mark_node)
- return;
- typedecl = TYPE_MAIN_DECL (type);
- list = DECL_FRIENDLIST (typedecl);
- name = DECL_NAME (decl);
- type = TREE_TYPE (typedecl);
- while (list)
- {
- if (name == FRIEND_NAME (list))
- {
- tree friends = FRIEND_DECLS (list);
- for (; friends ; friends = TREE_CHAIN (friends))
- {
- if (decl == TREE_VALUE (friends))
- {
- if (complain)
- warning (OPT_Wredundant_decls,
- "%qD is already a friend of class %qT",
- decl, type);
- return;
- }
- }
- maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
- TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
- TREE_VALUE (list));
- return;
- }
- list = TREE_CHAIN (list);
- }
- ctx = DECL_CONTEXT (decl);
- if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
- perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl,
- tf_warning_or_error);
- maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
- DECL_FRIENDLIST (typedecl)
- = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
- DECL_FRIENDLIST (typedecl));
- if (!uses_template_parms (type))
- DECL_BEFRIENDING_CLASSES (decl)
- = tree_cons (NULL_TREE, type,
- DECL_BEFRIENDING_CLASSES (decl));
- }
- /* 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!
- If COMPLAIN is true, warning about duplicate friend is issued.
- We want to have this diagnostics during parsing but not
- when a template is being instantiated. */
- void
- make_friend_class (tree type, tree friend_type, bool complain)
- {
- tree classes;
- /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
- the enclosing class. FRIEND_DEPTH counts the number of template
- headers used for this friend declaration. TEMPLATE_MEMBER_P,
- defined inside the `if' block for TYPENAME_TYPE case, is true if
- a template header in FRIEND_DEPTH is intended for DECLARATOR.
- For example, the code
- template <class T> struct A {
- template <class U> struct B {
- template <class V> template <class W>
- friend class C<V>::D;
- };
- };
- will eventually give the following results
- 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
- 2. FRIEND_DEPTH equals 2 (for `V' and `W').
- 3. TEMPLATE_MEMBER_P is true (for `W').
- The friend is a template friend iff FRIEND_DEPTH is nonzero. */
- int class_template_depth = template_class_depth (type);
- int friend_depth = processing_template_decl - class_template_depth;
- if (! MAYBE_CLASS_TYPE_P (friend_type)
- && TREE_CODE (friend_type) != TEMPLATE_TEMPLATE_PARM)
- {
- /* N1791: If the type specifier in a friend declaration designates a
- (possibly cv-qualified) class type, that class is declared as a
- friend; otherwise, the friend declaration is ignored.
- So don't complain in C++11 mode. */
- if (cxx_dialect < cxx11)
- pedwarn (input_location, complain ? 0 : OPT_Wpedantic,
- "invalid type %qT declared %<friend%>", friend_type);
- return;
- }
- friend_type = cv_unqualified (friend_type);
- if (check_for_bare_parameter_packs (friend_type))
- return;
- if (friend_depth)
- /* If the TYPE is a template then it makes sense for it to be
- friends with itself; this means that each instantiation is
- friends with all other instantiations. */
- {
- if (CLASS_TYPE_P (friend_type)
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
- && uses_template_parms (friend_type))
- {
- /* [temp.friend]
- Friend declarations shall not declare partial
- specializations. */
- error ("partial specialization %qT declared %<friend%>",
- friend_type);
- return;
- }
- }
- else if (same_type_p (type, friend_type))
- {
- if (complain)
- warning (0, "class %qT is implicitly friends with itself",
- type);
- return;
- }
- /* [temp.friend]
- A friend of a class or class template can be a function or
- class template, a specialization of a function template or
- class template, or an ordinary (nontemplate) function or
- class. */
- if (!friend_depth)
- ;/* ok */
- else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
- {
- if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
- == TEMPLATE_ID_EXPR)
- {
- /* template <class U> friend class T::X<U>; */
- /* [temp.friend]
- Friend declarations shall not declare partial
- specializations. */
- error ("partial specialization %qT declared %<friend%>",
- friend_type);
- return;
- }
- else
- {
- /* We will figure this out later. */
- bool template_member_p = false;
- tree ctype = TYPE_CONTEXT (friend_type);
- tree name = TYPE_IDENTIFIER (friend_type);
- tree decl;
- if (!uses_template_parms_level (ctype, class_template_depth
- + friend_depth))
- template_member_p = true;
- if (class_template_depth)
- {
- /* We rely on tsubst_friend_class to check the
- validity of the declaration later. */
- if (template_member_p)
- friend_type
- = make_unbound_class_template (ctype,
- name,
- current_template_parms,
- tf_error);
- else
- friend_type
- = make_typename_type (ctype, name, class_type, tf_error);
- }
- else
- {
- decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
- if (!decl)
- {
- error ("%qT is not a member of %qT", name, ctype);
- return;
- }
- if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
- {
- error ("%qT is not a member class template of %qT",
- name, ctype);
- inform (input_location, "%q+D declared here", decl);
- return;
- }
- if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
- || !CLASS_TYPE_P (TREE_TYPE (decl))))
- {
- error ("%qT is not a nested class of %qT",
- name, ctype);
- inform (input_location, "%q+D declared here", decl);
- return;
- }
- friend_type = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
- }
- }
- }
- else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
- {
- /* template <class T> friend class T; */
- error ("template parameter type %qT declared %<friend%>", friend_type);
- return;
- }
- else if (TREE_CODE (friend_type) == TEMPLATE_TEMPLATE_PARM)
- friend_type = TYPE_NAME (friend_type);
- else if (!CLASSTYPE_TEMPLATE_INFO (friend_type))
- {
- /* template <class T> friend class A; where A is not a template */
- error ("%q#T is not a template", friend_type);
- return;
- }
- else
- /* template <class T> friend class A; where A is a template */
- friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
- if (friend_type == error_mark_node)
- return;
- /* See if it is already a friend. */
- for (classes = CLASSTYPE_FRIEND_CLASSES (type);
- classes;
- classes = TREE_CHAIN (classes))
- {
- tree probe = TREE_VALUE (classes);
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- {
- if (friend_type == probe)
- {
- if (complain)
- warning (OPT_Wredundant_decls,
- "%qD is already a friend of %qT", probe, type);
- break;
- }
- }
- else if (TREE_CODE (probe) != TEMPLATE_DECL)
- {
- if (same_type_p (probe, friend_type))
- {
- if (complain)
- warning (OPT_Wredundant_decls,
- "%qT is already a friend of %qT", probe, type);
- break;
- }
- }
- }
- if (!classes)
- {
- maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
- CLASSTYPE_FRIEND_CLASSES (type)
- = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- 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));
- }
- }
- /* 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,
- 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;
- if (DECL_OVERRIDE_P (decl) || DECL_FINAL_P (decl))
- error ("friend declaration %qD may not have virt-specifiers",
- decl);
- /* 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);
- if (is_overloaded_fn (declarator))
- declarator = DECL_NAME (get_first_fn (declarator));
- }
- if (ctype)
- {
- /* CLASS_TEMPLATE_DEPTH counts the number of template headers for
- the enclosing class. FRIEND_DEPTH counts the number of template
- headers used for this friend declaration. TEMPLATE_MEMBER_P is
- true if a template header in FRIEND_DEPTH is intended for
- DECLARATOR. For example, the code
- template <class T> struct A {
- template <class U> struct B {
- template <class V> template <class W>
- friend void C<V>::f(W);
- };
- };
- will eventually give the following results
- 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U').
- 2. FRIEND_DEPTH equals 2 (for `V' and `W').
- 3. TEMPLATE_MEMBER_P is true (for `W'). */
- int class_template_depth = template_class_depth (current_class_type);
- int friend_depth = processing_template_decl - class_template_depth;
- /* We will figure this out later. */
- bool template_member_p = false;
- tree cname = TYPE_NAME (ctype);
- if (TREE_CODE (cname) == TYPE_DECL)
- cname = DECL_NAME (cname);
- /* A method friend. */
- if (flags == NO_SPECIAL && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
- grokclassfn (ctype, decl, flags);
- if (friend_depth)
- {
- if (!uses_template_parms_level (ctype, class_template_depth
- + friend_depth))
- template_member_p = true;
- }
- /* A nested class may declare a member of an enclosing class
- to be a friend, so we do lookup here even if CTYPE is in
- the process of being defined. */
- if (class_template_depth
- || COMPLETE_OR_OPEN_TYPE_P (ctype))
- {
- if (DECL_TEMPLATE_INFO (decl))
- /* DECL is a template specialization. No need to
- build a new TEMPLATE_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=*/true);
- else
- decl = check_classfn (ctype, decl,
- template_member_p
- ? current_template_parms
- : NULL_TREE);
- if ((template_member_p
- /* Always pull out the TEMPLATE_DECL if we have a friend
- template in a class template so that it gets tsubsted
- properly later on (59956). tsubst_friend_function knows
- how to tell this apart from a member template. */
- || (class_template_depth && friend_depth))
- && decl && TREE_CODE (decl) == FUNCTION_DECL)
- decl = DECL_TI_TEMPLATE (decl);
- if (decl)
- add_friend (current_class_type, decl, /*complain=*/true);
- }
- else
- error ("member %qD declared as friend before type %qT defined",
- decl, ctype);
- }
- /* A global friend.
- @@ or possibly a friend from a base class ?!? */
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
- /* 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. */
- if (funcdef_flag)
- SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
- if (! DECL_USE_TEMPLATE (decl))
- {
- /* We must check whether the decl refers to template
- arguments before push_template_decl_real adds a
- reference to the containing template class. */
- int warn = (warn_nontemplate_friend
- && ! funcdef_flag && ! is_friend_template
- && current_template_parms
- && uses_template_parms (decl));
- if (is_friend_template
- || template_class_depth (current_class_type) != 0)
- /* We can't call pushdecl for a template class, since in
- 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=*/true);
- else if (current_function_decl)
- {
- /* 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
- 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, /*is_friend=*/true);
- pop_nested_namespace (ns);
- }
- if (warn)
- {
- static int explained;
- bool warned;
- warned = warning (OPT_Wnon_template_friend, "friend declaration "
- "%q#D declares a non-template function", decl);
- if (! explained && warned)
- {
- 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;
- }
- }
- }
- if (decl == error_mark_node)
- return error_mark_node;
- add_friend (current_class_type,
- is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
- /*complain=*/true);
- DECL_FRIEND_P (decl) = 1;
- }
- return decl;
- }
|