xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/search.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Breadth-first and depth-first routines for
238fd1498Szrj    searching multiple-inheritance lattice for GNU C++.
338fd1498Szrj    Copyright (C) 1987-2018 Free Software Foundation, Inc.
438fd1498Szrj    Contributed by Michael Tiemann (tiemann@cygnus.com)
538fd1498Szrj 
638fd1498Szrj This file is part of GCC.
738fd1498Szrj 
838fd1498Szrj GCC is free software; you can redistribute it and/or modify
938fd1498Szrj it under the terms of the GNU General Public License as published by
1038fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1138fd1498Szrj any later version.
1238fd1498Szrj 
1338fd1498Szrj GCC is distributed in the hope that it will be useful,
1438fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1538fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1638fd1498Szrj GNU General Public License for more details.
1738fd1498Szrj 
1838fd1498Szrj You should have received a copy of the GNU General Public License
1938fd1498Szrj along with GCC; see the file COPYING3.  If not see
2038fd1498Szrj <http://www.gnu.org/licenses/>.  */
2138fd1498Szrj 
2238fd1498Szrj /* High-level class interface.  */
2338fd1498Szrj 
2438fd1498Szrj #include "config.h"
2538fd1498Szrj #include "system.h"
2638fd1498Szrj #include "coretypes.h"
2738fd1498Szrj #include "cp-tree.h"
2838fd1498Szrj #include "intl.h"
2938fd1498Szrj #include "toplev.h"
3038fd1498Szrj #include "spellcheck-tree.h"
3138fd1498Szrj #include "stringpool.h"
3238fd1498Szrj #include "attribs.h"
3338fd1498Szrj 
3438fd1498Szrj static int is_subobject_of_p (tree, tree);
3538fd1498Szrj static tree dfs_lookup_base (tree, void *);
3638fd1498Szrj static tree dfs_dcast_hint_pre (tree, void *);
3738fd1498Szrj static tree dfs_dcast_hint_post (tree, void *);
3838fd1498Szrj static tree dfs_debug_mark (tree, void *);
3938fd1498Szrj static int check_hidden_convs (tree, int, int, tree, tree, tree);
4038fd1498Szrj static tree split_conversions (tree, tree, tree, tree);
4138fd1498Szrj static int lookup_conversions_r (tree, int, int, tree, tree, tree *);
4238fd1498Szrj static int look_for_overrides_r (tree, tree);
4338fd1498Szrj static tree lookup_field_r (tree, void *);
4438fd1498Szrj static tree dfs_accessible_post (tree, void *);
4538fd1498Szrj static tree dfs_walk_once_accessible (tree, bool,
4638fd1498Szrj 				      tree (*pre_fn) (tree, void *),
4738fd1498Szrj 				      tree (*post_fn) (tree, void *),
4838fd1498Szrj 				      void *data);
4938fd1498Szrj static tree dfs_access_in_type (tree, void *);
5038fd1498Szrj static access_kind access_in_type (tree, tree);
5138fd1498Szrj static tree dfs_get_pure_virtuals (tree, void *);
5238fd1498Szrj 
5338fd1498Szrj 
5438fd1498Szrj /* Data for lookup_base and its workers.  */
5538fd1498Szrj 
5638fd1498Szrj struct lookup_base_data_s
5738fd1498Szrj {
5838fd1498Szrj   tree t;		/* type being searched.  */
5938fd1498Szrj   tree base;		/* The base type we're looking for.  */
6038fd1498Szrj   tree binfo;		/* Found binfo.  */
6138fd1498Szrj   bool via_virtual;	/* Found via a virtual path.  */
6238fd1498Szrj   bool ambiguous;	/* Found multiply ambiguous */
6338fd1498Szrj   bool repeated_base;	/* Whether there are repeated bases in the
6438fd1498Szrj 			    hierarchy.  */
6538fd1498Szrj   bool want_any;	/* Whether we want any matching binfo.  */
6638fd1498Szrj };
6738fd1498Szrj 
6838fd1498Szrj /* Worker function for lookup_base.  See if we've found the desired
6938fd1498Szrj    base and update DATA_ (a pointer to LOOKUP_BASE_DATA_S).  */
7038fd1498Szrj 
7138fd1498Szrj static tree
dfs_lookup_base(tree binfo,void * data_)7238fd1498Szrj dfs_lookup_base (tree binfo, void *data_)
7338fd1498Szrj {
7438fd1498Szrj   struct lookup_base_data_s *data = (struct lookup_base_data_s *) data_;
7538fd1498Szrj 
7638fd1498Szrj   if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), data->base))
7738fd1498Szrj     {
7838fd1498Szrj       if (!data->binfo)
7938fd1498Szrj 	{
8038fd1498Szrj 	  data->binfo = binfo;
8138fd1498Szrj 	  data->via_virtual
8238fd1498Szrj 	    = binfo_via_virtual (data->binfo, data->t) != NULL_TREE;
8338fd1498Szrj 
8438fd1498Szrj 	  if (!data->repeated_base)
8538fd1498Szrj 	    /* If there are no repeated bases, we can stop now.  */
8638fd1498Szrj 	    return binfo;
8738fd1498Szrj 
8838fd1498Szrj 	  if (data->want_any && !data->via_virtual)
8938fd1498Szrj 	    /* If this is a non-virtual base, then we can't do
9038fd1498Szrj 	       better.  */
9138fd1498Szrj 	    return binfo;
9238fd1498Szrj 
9338fd1498Szrj 	  return dfs_skip_bases;
9438fd1498Szrj 	}
9538fd1498Szrj       else
9638fd1498Szrj 	{
9738fd1498Szrj 	  gcc_assert (binfo != data->binfo);
9838fd1498Szrj 
9938fd1498Szrj 	  /* We've found more than one matching binfo.  */
10038fd1498Szrj 	  if (!data->want_any)
10138fd1498Szrj 	    {
10238fd1498Szrj 	      /* This is immediately ambiguous.  */
10338fd1498Szrj 	      data->binfo = NULL_TREE;
10438fd1498Szrj 	      data->ambiguous = true;
10538fd1498Szrj 	      return error_mark_node;
10638fd1498Szrj 	    }
10738fd1498Szrj 
10838fd1498Szrj 	  /* Prefer one via a non-virtual path.  */
10938fd1498Szrj 	  if (!binfo_via_virtual (binfo, data->t))
11038fd1498Szrj 	    {
11138fd1498Szrj 	      data->binfo = binfo;
11238fd1498Szrj 	      data->via_virtual = false;
11338fd1498Szrj 	      return binfo;
11438fd1498Szrj 	    }
11538fd1498Szrj 
11638fd1498Szrj 	  /* There must be repeated bases, otherwise we'd have stopped
11738fd1498Szrj 	     on the first base we found.  */
11838fd1498Szrj 	  return dfs_skip_bases;
11938fd1498Szrj 	}
12038fd1498Szrj     }
12138fd1498Szrj 
12238fd1498Szrj   return NULL_TREE;
12338fd1498Szrj }
12438fd1498Szrj 
12538fd1498Szrj /* Returns true if type BASE is accessible in T.  (BASE is known to be
12638fd1498Szrj    a (possibly non-proper) base class of T.)  If CONSIDER_LOCAL_P is
12738fd1498Szrj    true, consider any special access of the current scope, or access
12838fd1498Szrj    bestowed by friendship.  */
12938fd1498Szrj 
13038fd1498Szrj bool
accessible_base_p(tree t,tree base,bool consider_local_p)13138fd1498Szrj accessible_base_p (tree t, tree base, bool consider_local_p)
13238fd1498Szrj {
13338fd1498Szrj   tree decl;
13438fd1498Szrj 
13538fd1498Szrj   /* [class.access.base]
13638fd1498Szrj 
13738fd1498Szrj      A base class is said to be accessible if an invented public
13838fd1498Szrj      member of the base class is accessible.
13938fd1498Szrj 
14038fd1498Szrj      If BASE is a non-proper base, this condition is trivially
14138fd1498Szrj      true.  */
14238fd1498Szrj   if (same_type_p (t, base))
14338fd1498Szrj     return true;
14438fd1498Szrj   /* Rather than inventing a public member, we use the implicit
14538fd1498Szrj      public typedef created in the scope of every class.  */
14638fd1498Szrj   decl = TYPE_FIELDS (base);
14738fd1498Szrj   while (!DECL_SELF_REFERENCE_P (decl))
14838fd1498Szrj     decl = DECL_CHAIN (decl);
14938fd1498Szrj   while (ANON_AGGR_TYPE_P (t))
15038fd1498Szrj     t = TYPE_CONTEXT (t);
15138fd1498Szrj   return accessible_p (t, decl, consider_local_p);
15238fd1498Szrj }
15338fd1498Szrj 
15438fd1498Szrj /* Lookup BASE in the hierarchy dominated by T.  Do access checking as
15538fd1498Szrj    ACCESS specifies.  Return the binfo we discover.  If KIND_PTR is
15638fd1498Szrj    non-NULL, fill with information about what kind of base we
15738fd1498Szrj    discovered.
15838fd1498Szrj 
15938fd1498Szrj    If the base is inaccessible, or ambiguous, then error_mark_node is
16038fd1498Szrj    returned.  If the tf_error bit of COMPLAIN is not set, no error
16138fd1498Szrj    is issued.  */
16238fd1498Szrj 
16338fd1498Szrj tree
lookup_base(tree t,tree base,base_access access,base_kind * kind_ptr,tsubst_flags_t complain)16438fd1498Szrj lookup_base (tree t, tree base, base_access access,
16538fd1498Szrj 	     base_kind *kind_ptr, tsubst_flags_t complain)
16638fd1498Szrj {
16738fd1498Szrj   tree binfo;
16838fd1498Szrj   tree t_binfo;
16938fd1498Szrj   base_kind bk;
17038fd1498Szrj 
17138fd1498Szrj   /* "Nothing" is definitely not derived from Base.  */
17238fd1498Szrj   if (t == NULL_TREE)
17338fd1498Szrj     {
17438fd1498Szrj       if (kind_ptr)
17538fd1498Szrj 	*kind_ptr = bk_not_base;
17638fd1498Szrj       return NULL_TREE;
17738fd1498Szrj     }
17838fd1498Szrj 
17938fd1498Szrj   if (t == error_mark_node || base == error_mark_node)
18038fd1498Szrj     {
18138fd1498Szrj       if (kind_ptr)
18238fd1498Szrj 	*kind_ptr = bk_not_base;
18338fd1498Szrj       return error_mark_node;
18438fd1498Szrj     }
18538fd1498Szrj   gcc_assert (TYPE_P (base));
18638fd1498Szrj 
18738fd1498Szrj   if (!TYPE_P (t))
18838fd1498Szrj     {
18938fd1498Szrj       t_binfo = t;
19038fd1498Szrj       t = BINFO_TYPE (t);
19138fd1498Szrj     }
19238fd1498Szrj   else
19338fd1498Szrj     {
19438fd1498Szrj       t = complete_type (TYPE_MAIN_VARIANT (t));
195*58e805e6Szrj       if (dependent_type_p (t))
196*58e805e6Szrj 	if (tree open = currently_open_class (t))
197*58e805e6Szrj 	  t = open;
19838fd1498Szrj       t_binfo = TYPE_BINFO (t);
19938fd1498Szrj     }
20038fd1498Szrj 
20138fd1498Szrj   base = TYPE_MAIN_VARIANT (base);
20238fd1498Szrj 
20338fd1498Szrj   /* If BASE is incomplete, it can't be a base of T--and instantiating it
20438fd1498Szrj      might cause an error.  */
20538fd1498Szrj   if (t_binfo && CLASS_TYPE_P (base) && COMPLETE_OR_OPEN_TYPE_P (base))
20638fd1498Szrj     {
20738fd1498Szrj       struct lookup_base_data_s data;
20838fd1498Szrj 
20938fd1498Szrj       data.t = t;
21038fd1498Szrj       data.base = base;
21138fd1498Szrj       data.binfo = NULL_TREE;
21238fd1498Szrj       data.ambiguous = data.via_virtual = false;
21338fd1498Szrj       data.repeated_base = CLASSTYPE_REPEATED_BASE_P (t);
21438fd1498Szrj       data.want_any = access == ba_any;
21538fd1498Szrj 
21638fd1498Szrj       dfs_walk_once (t_binfo, dfs_lookup_base, NULL, &data);
21738fd1498Szrj       binfo = data.binfo;
21838fd1498Szrj 
21938fd1498Szrj       if (!binfo)
22038fd1498Szrj 	bk = data.ambiguous ? bk_ambig : bk_not_base;
22138fd1498Szrj       else if (binfo == t_binfo)
22238fd1498Szrj 	bk = bk_same_type;
22338fd1498Szrj       else if (data.via_virtual)
22438fd1498Szrj 	bk = bk_via_virtual;
22538fd1498Szrj       else
22638fd1498Szrj 	bk = bk_proper_base;
22738fd1498Szrj     }
22838fd1498Szrj   else
22938fd1498Szrj     {
23038fd1498Szrj       binfo = NULL_TREE;
23138fd1498Szrj       bk = bk_not_base;
23238fd1498Szrj     }
23338fd1498Szrj 
23438fd1498Szrj   /* Check that the base is unambiguous and accessible.  */
23538fd1498Szrj   if (access != ba_any)
23638fd1498Szrj     switch (bk)
23738fd1498Szrj       {
23838fd1498Szrj       case bk_not_base:
23938fd1498Szrj 	break;
24038fd1498Szrj 
24138fd1498Szrj       case bk_ambig:
24238fd1498Szrj 	if (complain & tf_error)
24338fd1498Szrj 	  error ("%qT is an ambiguous base of %qT", base, t);
24438fd1498Szrj 	binfo = error_mark_node;
24538fd1498Szrj 	break;
24638fd1498Szrj 
24738fd1498Szrj       default:
24838fd1498Szrj 	if ((access & ba_check_bit)
24938fd1498Szrj 	    /* If BASE is incomplete, then BASE and TYPE are probably
25038fd1498Szrj 	       the same, in which case BASE is accessible.  If they
25138fd1498Szrj 	       are not the same, then TYPE is invalid.  In that case,
25238fd1498Szrj 	       there's no need to issue another error here, and
25338fd1498Szrj 	       there's no implicit typedef to use in the code that
25438fd1498Szrj 	       follows, so we skip the check.  */
25538fd1498Szrj 	    && COMPLETE_TYPE_P (base)
25638fd1498Szrj 	    && !accessible_base_p (t, base, !(access & ba_ignore_scope)))
25738fd1498Szrj 	  {
25838fd1498Szrj 	    if (complain & tf_error)
25938fd1498Szrj 	      error ("%qT is an inaccessible base of %qT", base, t);
26038fd1498Szrj 	    binfo = error_mark_node;
26138fd1498Szrj 	    bk = bk_inaccessible;
26238fd1498Szrj 	  }
26338fd1498Szrj 	break;
26438fd1498Szrj       }
26538fd1498Szrj 
26638fd1498Szrj   if (kind_ptr)
26738fd1498Szrj     *kind_ptr = bk;
26838fd1498Szrj 
26938fd1498Szrj   return binfo;
27038fd1498Szrj }
27138fd1498Szrj 
27238fd1498Szrj /* Data for dcast_base_hint walker.  */
27338fd1498Szrj 
27438fd1498Szrj struct dcast_data_s
27538fd1498Szrj {
27638fd1498Szrj   tree subtype;   /* The base type we're looking for.  */
27738fd1498Szrj   int virt_depth; /* Number of virtual bases encountered from most
27838fd1498Szrj 		     derived.  */
27938fd1498Szrj   tree offset;    /* Best hint offset discovered so far.  */
28038fd1498Szrj   bool repeated_base;  /* Whether there are repeated bases in the
28138fd1498Szrj 			  hierarchy.  */
28238fd1498Szrj };
28338fd1498Szrj 
28438fd1498Szrj /* Worker for dcast_base_hint.  Search for the base type being cast
28538fd1498Szrj    from.  */
28638fd1498Szrj 
28738fd1498Szrj static tree
dfs_dcast_hint_pre(tree binfo,void * data_)28838fd1498Szrj dfs_dcast_hint_pre (tree binfo, void *data_)
28938fd1498Szrj {
29038fd1498Szrj   struct dcast_data_s *data = (struct dcast_data_s *) data_;
29138fd1498Szrj 
29238fd1498Szrj   if (BINFO_VIRTUAL_P (binfo))
29338fd1498Szrj     data->virt_depth++;
29438fd1498Szrj 
29538fd1498Szrj   if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), data->subtype))
29638fd1498Szrj     {
29738fd1498Szrj       if (data->virt_depth)
29838fd1498Szrj 	{
29938fd1498Szrj 	  data->offset = ssize_int (-1);
30038fd1498Szrj 	  return data->offset;
30138fd1498Szrj 	}
30238fd1498Szrj       if (data->offset)
30338fd1498Szrj 	data->offset = ssize_int (-3);
30438fd1498Szrj       else
30538fd1498Szrj 	data->offset = BINFO_OFFSET (binfo);
30638fd1498Szrj 
30738fd1498Szrj       return data->repeated_base ? dfs_skip_bases : data->offset;
30838fd1498Szrj     }
30938fd1498Szrj 
31038fd1498Szrj   return NULL_TREE;
31138fd1498Szrj }
31238fd1498Szrj 
31338fd1498Szrj /* Worker for dcast_base_hint.  Track the virtual depth.  */
31438fd1498Szrj 
31538fd1498Szrj static tree
dfs_dcast_hint_post(tree binfo,void * data_)31638fd1498Szrj dfs_dcast_hint_post (tree binfo, void *data_)
31738fd1498Szrj {
31838fd1498Szrj   struct dcast_data_s *data = (struct dcast_data_s *) data_;
31938fd1498Szrj 
32038fd1498Szrj   if (BINFO_VIRTUAL_P (binfo))
32138fd1498Szrj     data->virt_depth--;
32238fd1498Szrj 
32338fd1498Szrj   return NULL_TREE;
32438fd1498Szrj }
32538fd1498Szrj 
32638fd1498Szrj /* The dynamic cast runtime needs a hint about how the static SUBTYPE type
32738fd1498Szrj    started from is related to the required TARGET type, in order to optimize
32838fd1498Szrj    the inheritance graph search. This information is independent of the
32938fd1498Szrj    current context, and ignores private paths, hence get_base_distance is
33038fd1498Szrj    inappropriate. Return a TREE specifying the base offset, BOFF.
33138fd1498Szrj    BOFF >= 0, there is only one public non-virtual SUBTYPE base at offset BOFF,
33238fd1498Szrj       and there are no public virtual SUBTYPE bases.
33338fd1498Szrj    BOFF == -1, SUBTYPE occurs as multiple public virtual or non-virtual bases.
33438fd1498Szrj    BOFF == -2, SUBTYPE is not a public base.
33538fd1498Szrj    BOFF == -3, SUBTYPE occurs as multiple public non-virtual bases.  */
33638fd1498Szrj 
33738fd1498Szrj tree
dcast_base_hint(tree subtype,tree target)33838fd1498Szrj dcast_base_hint (tree subtype, tree target)
33938fd1498Szrj {
34038fd1498Szrj   struct dcast_data_s data;
34138fd1498Szrj 
34238fd1498Szrj   data.subtype = subtype;
34338fd1498Szrj   data.virt_depth = 0;
34438fd1498Szrj   data.offset = NULL_TREE;
34538fd1498Szrj   data.repeated_base = CLASSTYPE_REPEATED_BASE_P (target);
34638fd1498Szrj 
34738fd1498Szrj   dfs_walk_once_accessible (TYPE_BINFO (target), /*friends=*/false,
34838fd1498Szrj 			    dfs_dcast_hint_pre, dfs_dcast_hint_post, &data);
34938fd1498Szrj   return data.offset ? data.offset : ssize_int (-2);
35038fd1498Szrj }
35138fd1498Szrj 
35238fd1498Szrj /* Search for a member with name NAME in a multiple inheritance
35338fd1498Szrj    lattice specified by TYPE.  If it does not exist, return NULL_TREE.
35438fd1498Szrj    If the member is ambiguously referenced, return `error_mark_node'.
35538fd1498Szrj    Otherwise, return a DECL with the indicated name.  If WANT_TYPE is
35638fd1498Szrj    true, type declarations are preferred.  */
35738fd1498Szrj 
35838fd1498Szrj /* Return the FUNCTION_DECL, RECORD_TYPE, UNION_TYPE, or
35938fd1498Szrj    NAMESPACE_DECL corresponding to the innermost non-block scope.  */
36038fd1498Szrj 
36138fd1498Szrj tree
current_scope(void)36238fd1498Szrj current_scope (void)
36338fd1498Szrj {
36438fd1498Szrj   /* There are a number of cases we need to be aware of here:
36538fd1498Szrj 			 current_class_type	current_function_decl
36638fd1498Szrj      global			NULL			NULL
36738fd1498Szrj      fn-local			NULL			SET
36838fd1498Szrj      class-local		SET			NULL
36938fd1498Szrj      class->fn			SET			SET
37038fd1498Szrj      fn->class			SET			SET
37138fd1498Szrj 
37238fd1498Szrj      Those last two make life interesting.  If we're in a function which is
37338fd1498Szrj      itself inside a class, we need decls to go into the fn's decls (our
37438fd1498Szrj      second case below).  But if we're in a class and the class itself is
37538fd1498Szrj      inside a function, we need decls to go into the decls for the class.  To
37638fd1498Szrj      achieve this last goal, we must see if, when both current_class_ptr and
37738fd1498Szrj      current_function_decl are set, the class was declared inside that
37838fd1498Szrj      function.  If so, we know to put the decls into the class's scope.  */
37938fd1498Szrj   if (current_function_decl && current_class_type
38038fd1498Szrj       && ((DECL_FUNCTION_MEMBER_P (current_function_decl)
38138fd1498Szrj 	   && same_type_p (DECL_CONTEXT (current_function_decl),
38238fd1498Szrj 			   current_class_type))
38338fd1498Szrj 	  || (DECL_FRIEND_CONTEXT (current_function_decl)
38438fd1498Szrj 	      && same_type_p (DECL_FRIEND_CONTEXT (current_function_decl),
38538fd1498Szrj 			      current_class_type))))
38638fd1498Szrj     return current_function_decl;
38738fd1498Szrj 
38838fd1498Szrj   if (current_class_type)
38938fd1498Szrj     return current_class_type;
39038fd1498Szrj 
39138fd1498Szrj   if (current_function_decl)
39238fd1498Szrj     return current_function_decl;
39338fd1498Szrj 
39438fd1498Szrj   return current_namespace;
39538fd1498Szrj }
39638fd1498Szrj 
39738fd1498Szrj /* Returns nonzero if we are currently in a function scope.  Note
39838fd1498Szrj    that this function returns zero if we are within a local class, but
39938fd1498Szrj    not within a member function body of the local class.  */
40038fd1498Szrj 
40138fd1498Szrj int
at_function_scope_p(void)40238fd1498Szrj at_function_scope_p (void)
40338fd1498Szrj {
40438fd1498Szrj   tree cs = current_scope ();
40538fd1498Szrj   /* Also check cfun to make sure that we're really compiling
40638fd1498Szrj      this function (as opposed to having set current_function_decl
40738fd1498Szrj      for access checking or some such).  */
40838fd1498Szrj   return (cs && TREE_CODE (cs) == FUNCTION_DECL
40938fd1498Szrj 	  && cfun && cfun->decl == current_function_decl);
41038fd1498Szrj }
41138fd1498Szrj 
41238fd1498Szrj /* Returns true if the innermost active scope is a class scope.  */
41338fd1498Szrj 
41438fd1498Szrj bool
at_class_scope_p(void)41538fd1498Szrj at_class_scope_p (void)
41638fd1498Szrj {
41738fd1498Szrj   tree cs = current_scope ();
41838fd1498Szrj   return cs && TYPE_P (cs);
41938fd1498Szrj }
42038fd1498Szrj 
42138fd1498Szrj /* Returns true if the innermost active scope is a namespace scope.  */
42238fd1498Szrj 
42338fd1498Szrj bool
at_namespace_scope_p(void)42438fd1498Szrj at_namespace_scope_p (void)
42538fd1498Szrj {
42638fd1498Szrj   tree cs = current_scope ();
42738fd1498Szrj   return cs && TREE_CODE (cs) == NAMESPACE_DECL;
42838fd1498Szrj }
42938fd1498Szrj 
43038fd1498Szrj /* Return the scope of DECL, as appropriate when doing name-lookup.  */
43138fd1498Szrj 
43238fd1498Szrj tree
context_for_name_lookup(tree decl)43338fd1498Szrj context_for_name_lookup (tree decl)
43438fd1498Szrj {
43538fd1498Szrj   /* [class.union]
43638fd1498Szrj 
43738fd1498Szrj      For the purposes of name lookup, after the anonymous union
43838fd1498Szrj      definition, the members of the anonymous union are considered to
43938fd1498Szrj      have been defined in the scope in which the anonymous union is
44038fd1498Szrj      declared.  */
44138fd1498Szrj   tree context = DECL_CONTEXT (decl);
44238fd1498Szrj 
44338fd1498Szrj   while (context && TYPE_P (context)
44438fd1498Szrj 	 && (ANON_AGGR_TYPE_P (context) || UNSCOPED_ENUM_P (context)))
44538fd1498Szrj     context = TYPE_CONTEXT (context);
44638fd1498Szrj   if (!context)
44738fd1498Szrj     context = global_namespace;
44838fd1498Szrj 
44938fd1498Szrj   return context;
45038fd1498Szrj }
45138fd1498Szrj 
45238fd1498Szrj /* Returns true iff DECL is declared in TYPE.  */
45338fd1498Szrj 
45438fd1498Szrj static bool
member_declared_in_type(tree decl,tree type)45538fd1498Szrj member_declared_in_type (tree decl, tree type)
45638fd1498Szrj {
45738fd1498Szrj   /* A normal declaration obviously counts.  */
45838fd1498Szrj   if (context_for_name_lookup (decl) == type)
45938fd1498Szrj     return true;
46038fd1498Szrj   /* So does a using or access declaration.  */
46138fd1498Szrj   if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl)
46238fd1498Szrj       && purpose_member (type, DECL_ACCESS (decl)))
46338fd1498Szrj     return true;
46438fd1498Szrj   return false;
46538fd1498Szrj }
46638fd1498Szrj 
46738fd1498Szrj /* The accessibility routines use BINFO_ACCESS for scratch space
46838fd1498Szrj    during the computation of the accessibility of some declaration.  */
46938fd1498Szrj 
47038fd1498Szrj /* Avoid walking up past a declaration of the member.  */
47138fd1498Szrj 
47238fd1498Szrj static tree
dfs_access_in_type_pre(tree binfo,void * data)47338fd1498Szrj dfs_access_in_type_pre (tree binfo, void *data)
47438fd1498Szrj {
47538fd1498Szrj   tree decl = (tree) data;
47638fd1498Szrj   tree type = BINFO_TYPE (binfo);
47738fd1498Szrj   if (member_declared_in_type (decl, type))
47838fd1498Szrj     return dfs_skip_bases;
47938fd1498Szrj   return NULL_TREE;
48038fd1498Szrj }
48138fd1498Szrj 
48238fd1498Szrj #define BINFO_ACCESS(NODE) \
48338fd1498Szrj   ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
48438fd1498Szrj 
48538fd1498Szrj /* Set the access associated with NODE to ACCESS.  */
48638fd1498Szrj 
48738fd1498Szrj #define SET_BINFO_ACCESS(NODE, ACCESS)			\
48838fd1498Szrj   ((TREE_PUBLIC (NODE) = ((ACCESS) & 2) != 0),	\
48938fd1498Szrj    (TREE_PRIVATE (NODE) = ((ACCESS) & 1) != 0))
49038fd1498Szrj 
49138fd1498Szrj /* Called from access_in_type via dfs_walk.  Calculate the access to
49238fd1498Szrj    DATA (which is really a DECL) in BINFO.  */
49338fd1498Szrj 
49438fd1498Szrj static tree
dfs_access_in_type(tree binfo,void * data)49538fd1498Szrj dfs_access_in_type (tree binfo, void *data)
49638fd1498Szrj {
49738fd1498Szrj   tree decl = (tree) data;
49838fd1498Szrj   tree type = BINFO_TYPE (binfo);
49938fd1498Szrj   access_kind access = ak_none;
50038fd1498Szrj 
50138fd1498Szrj   if (context_for_name_lookup (decl) == type)
50238fd1498Szrj     {
50338fd1498Szrj       /* If we have descended to the scope of DECL, just note the
50438fd1498Szrj 	 appropriate access.  */
50538fd1498Szrj       if (TREE_PRIVATE (decl))
50638fd1498Szrj 	access = ak_private;
50738fd1498Szrj       else if (TREE_PROTECTED (decl))
50838fd1498Szrj 	access = ak_protected;
50938fd1498Szrj       else
51038fd1498Szrj 	access = ak_public;
51138fd1498Szrj     }
51238fd1498Szrj   else
51338fd1498Szrj     {
51438fd1498Szrj       /* First, check for an access-declaration that gives us more
51538fd1498Szrj 	 access to the DECL.  */
51638fd1498Szrj       if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
51738fd1498Szrj 	{
51838fd1498Szrj 	  tree decl_access = purpose_member (type, DECL_ACCESS (decl));
51938fd1498Szrj 
52038fd1498Szrj 	  if (decl_access)
52138fd1498Szrj 	    {
52238fd1498Szrj 	      decl_access = TREE_VALUE (decl_access);
52338fd1498Szrj 
52438fd1498Szrj 	      if (decl_access == access_public_node)
52538fd1498Szrj 		access = ak_public;
52638fd1498Szrj 	      else if (decl_access == access_protected_node)
52738fd1498Szrj 		access = ak_protected;
52838fd1498Szrj 	      else if (decl_access == access_private_node)
52938fd1498Szrj 		access = ak_private;
53038fd1498Szrj 	      else
53138fd1498Szrj 		gcc_unreachable ();
53238fd1498Szrj 	    }
53338fd1498Szrj 	}
53438fd1498Szrj 
53538fd1498Szrj       if (!access)
53638fd1498Szrj 	{
53738fd1498Szrj 	  int i;
53838fd1498Szrj 	  tree base_binfo;
53938fd1498Szrj 	  vec<tree, va_gc> *accesses;
54038fd1498Szrj 
54138fd1498Szrj 	  /* Otherwise, scan our baseclasses, and pick the most favorable
54238fd1498Szrj 	     access.  */
54338fd1498Szrj 	  accesses = BINFO_BASE_ACCESSES (binfo);
54438fd1498Szrj 	  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
54538fd1498Szrj 	    {
54638fd1498Szrj 	      tree base_access = (*accesses)[i];
54738fd1498Szrj 	      access_kind base_access_now = BINFO_ACCESS (base_binfo);
54838fd1498Szrj 
54938fd1498Szrj 	      if (base_access_now == ak_none || base_access_now == ak_private)
55038fd1498Szrj 		/* If it was not accessible in the base, or only
55138fd1498Szrj 		   accessible as a private member, we can't access it
55238fd1498Szrj 		   all.  */
55338fd1498Szrj 		base_access_now = ak_none;
55438fd1498Szrj 	      else if (base_access == access_protected_node)
55538fd1498Szrj 		/* Public and protected members in the base become
55638fd1498Szrj 		   protected here.  */
55738fd1498Szrj 		base_access_now = ak_protected;
55838fd1498Szrj 	      else if (base_access == access_private_node)
55938fd1498Szrj 		/* Public and protected members in the base become
56038fd1498Szrj 		   private here.  */
56138fd1498Szrj 		base_access_now = ak_private;
56238fd1498Szrj 
56338fd1498Szrj 	      /* See if the new access, via this base, gives more
56438fd1498Szrj 		 access than our previous best access.  */
56538fd1498Szrj 	      if (base_access_now != ak_none
56638fd1498Szrj 		  && (access == ak_none || base_access_now < access))
56738fd1498Szrj 		{
56838fd1498Szrj 		  access = base_access_now;
56938fd1498Szrj 
57038fd1498Szrj 		  /* If the new access is public, we can't do better.  */
57138fd1498Szrj 		  if (access == ak_public)
57238fd1498Szrj 		    break;
57338fd1498Szrj 		}
57438fd1498Szrj 	    }
57538fd1498Szrj 	}
57638fd1498Szrj     }
57738fd1498Szrj 
57838fd1498Szrj   /* Note the access to DECL in TYPE.  */
57938fd1498Szrj   SET_BINFO_ACCESS (binfo, access);
58038fd1498Szrj 
58138fd1498Szrj   return NULL_TREE;
58238fd1498Szrj }
58338fd1498Szrj 
58438fd1498Szrj /* Return the access to DECL in TYPE.  */
58538fd1498Szrj 
58638fd1498Szrj static access_kind
access_in_type(tree type,tree decl)58738fd1498Szrj access_in_type (tree type, tree decl)
58838fd1498Szrj {
58938fd1498Szrj   tree binfo = TYPE_BINFO (type);
59038fd1498Szrj 
59138fd1498Szrj   /* We must take into account
59238fd1498Szrj 
59338fd1498Szrj        [class.paths]
59438fd1498Szrj 
59538fd1498Szrj        If a name can be reached by several paths through a multiple
59638fd1498Szrj        inheritance graph, the access is that of the path that gives
59738fd1498Szrj        most access.
59838fd1498Szrj 
59938fd1498Szrj     The algorithm we use is to make a post-order depth-first traversal
60038fd1498Szrj     of the base-class hierarchy.  As we come up the tree, we annotate
60138fd1498Szrj     each node with the most lenient access.  */
60238fd1498Szrj   dfs_walk_once (binfo, dfs_access_in_type_pre, dfs_access_in_type, decl);
60338fd1498Szrj 
60438fd1498Szrj   return BINFO_ACCESS (binfo);
60538fd1498Szrj }
60638fd1498Szrj 
60738fd1498Szrj /* Returns nonzero if it is OK to access DECL named in TYPE through an object
60838fd1498Szrj    of OTYPE in the context of DERIVED.  */
60938fd1498Szrj 
61038fd1498Szrj static int
protected_accessible_p(tree decl,tree derived,tree type,tree otype)61138fd1498Szrj protected_accessible_p (tree decl, tree derived, tree type, tree otype)
61238fd1498Szrj {
61338fd1498Szrj   /* We're checking this clause from [class.access.base]
61438fd1498Szrj 
61538fd1498Szrj        m as a member of N is protected, and the reference occurs in a
61638fd1498Szrj        member or friend of class N, or in a member or friend of a
61738fd1498Szrj        class P derived from N, where m as a member of P is public, private
61838fd1498Szrj        or protected.
61938fd1498Szrj 
62038fd1498Szrj     Here DERIVED is a possible P, DECL is m and TYPE is N.  */
62138fd1498Szrj 
62238fd1498Szrj   /* If DERIVED isn't derived from N, then it can't be a P.  */
62338fd1498Szrj   if (!DERIVED_FROM_P (type, derived))
62438fd1498Szrj     return 0;
62538fd1498Szrj 
62638fd1498Szrj   /* [class.protected]
62738fd1498Szrj 
62838fd1498Szrj      When a friend or a member function of a derived class references
62938fd1498Szrj      a protected nonstatic member of a base class, an access check
63038fd1498Szrj      applies in addition to those described earlier in clause
63138fd1498Szrj      _class.access_) Except when forming a pointer to member
63238fd1498Szrj      (_expr.unary.op_), the access must be through a pointer to,
63338fd1498Szrj      reference to, or object of the derived class itself (or any class
63438fd1498Szrj      derived from that class) (_expr.ref_).  If the access is to form
63538fd1498Szrj      a pointer to member, the nested-name-specifier shall name the
63638fd1498Szrj      derived class (or any class derived from that class).  */
63738fd1498Szrj   if (DECL_NONSTATIC_MEMBER_P (decl)
63838fd1498Szrj       && !DERIVED_FROM_P (derived, otype))
63938fd1498Szrj     return 0;
64038fd1498Szrj 
64138fd1498Szrj   return 1;
64238fd1498Szrj }
64338fd1498Szrj 
64438fd1498Szrj /* Returns nonzero if SCOPE is a type or a friend of a type which would be able
64538fd1498Szrj    to access DECL through TYPE.  OTYPE is the type of the object.  */
64638fd1498Szrj 
64738fd1498Szrj static int
friend_accessible_p(tree scope,tree decl,tree type,tree otype)64838fd1498Szrj friend_accessible_p (tree scope, tree decl, tree type, tree otype)
64938fd1498Szrj {
65038fd1498Szrj   /* We're checking this clause from [class.access.base]
65138fd1498Szrj 
65238fd1498Szrj        m as a member of N is protected, and the reference occurs in a
65338fd1498Szrj        member or friend of class N, or in a member or friend of a
65438fd1498Szrj        class P derived from N, where m as a member of P is public, private
65538fd1498Szrj        or protected.
65638fd1498Szrj 
65738fd1498Szrj     Here DECL is m and TYPE is N.  SCOPE is the current context,
65838fd1498Szrj     and we check all its possible Ps.  */
65938fd1498Szrj   tree befriending_classes;
66038fd1498Szrj   tree t;
66138fd1498Szrj 
66238fd1498Szrj   if (!scope)
66338fd1498Szrj     return 0;
66438fd1498Szrj 
66538fd1498Szrj   if (is_global_friend (scope))
66638fd1498Szrj     return 1;
66738fd1498Szrj 
66838fd1498Szrj   /* Is SCOPE itself a suitable P?  */
66938fd1498Szrj   if (TYPE_P (scope) && protected_accessible_p (decl, scope, type, otype))
67038fd1498Szrj     return 1;
67138fd1498Szrj 
67238fd1498Szrj   if (DECL_DECLARES_FUNCTION_P (scope))
67338fd1498Szrj     befriending_classes = DECL_BEFRIENDING_CLASSES (scope);
67438fd1498Szrj   else if (TYPE_P (scope))
67538fd1498Szrj     befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope);
67638fd1498Szrj   else
67738fd1498Szrj     return 0;
67838fd1498Szrj 
67938fd1498Szrj   for (t = befriending_classes; t; t = TREE_CHAIN (t))
68038fd1498Szrj     if (protected_accessible_p (decl, TREE_VALUE (t), type, otype))
68138fd1498Szrj       return 1;
68238fd1498Szrj 
68338fd1498Szrj   /* Nested classes have the same access as their enclosing types, as
68438fd1498Szrj      per DR 45 (this is a change from C++98).  */
68538fd1498Szrj   if (TYPE_P (scope))
68638fd1498Szrj     if (friend_accessible_p (TYPE_CONTEXT (scope), decl, type, otype))
68738fd1498Szrj       return 1;
68838fd1498Szrj 
68938fd1498Szrj   if (DECL_DECLARES_FUNCTION_P (scope))
69038fd1498Szrj     {
69138fd1498Szrj       /* Perhaps this SCOPE is a member of a class which is a
69238fd1498Szrj 	 friend.  */
69338fd1498Szrj       if (DECL_CLASS_SCOPE_P (scope)
69438fd1498Szrj 	  && friend_accessible_p (DECL_CONTEXT (scope), decl, type, otype))
69538fd1498Szrj 	return 1;
69638fd1498Szrj     }
69738fd1498Szrj 
69838fd1498Szrj   /* Maybe scope's template is a friend.  */
69938fd1498Szrj   if (tree tinfo = get_template_info (scope))
70038fd1498Szrj     {
70138fd1498Szrj       tree tmpl = TI_TEMPLATE (tinfo);
70238fd1498Szrj       if (DECL_CLASS_TEMPLATE_P (tmpl))
70338fd1498Szrj 	tmpl = TREE_TYPE (tmpl);
70438fd1498Szrj       else
70538fd1498Szrj 	tmpl = DECL_TEMPLATE_RESULT (tmpl);
70638fd1498Szrj       if (tmpl != scope)
70738fd1498Szrj 	{
70838fd1498Szrj 	  /* Increment processing_template_decl to make sure that
70938fd1498Szrj 	     dependent_type_p works correctly.  */
71038fd1498Szrj 	  ++processing_template_decl;
71138fd1498Szrj 	  int ret = friend_accessible_p (tmpl, decl, type, otype);
71238fd1498Szrj 	  --processing_template_decl;
71338fd1498Szrj 	  if (ret)
71438fd1498Szrj 	    return 1;
71538fd1498Szrj 	}
71638fd1498Szrj     }
71738fd1498Szrj 
71838fd1498Szrj   /* If is_friend is true, we should have found a befriending class.  */
71938fd1498Szrj   gcc_checking_assert (!is_friend (type, scope));
72038fd1498Szrj 
72138fd1498Szrj   return 0;
72238fd1498Szrj }
72338fd1498Szrj 
72438fd1498Szrj struct dfs_accessible_data
72538fd1498Szrj {
72638fd1498Szrj   tree decl;
72738fd1498Szrj   tree object_type;
72838fd1498Szrj };
72938fd1498Szrj 
73038fd1498Szrj /* Avoid walking up past a declaration of the member.  */
73138fd1498Szrj 
73238fd1498Szrj static tree
dfs_accessible_pre(tree binfo,void * data)73338fd1498Szrj dfs_accessible_pre (tree binfo, void *data)
73438fd1498Szrj {
73538fd1498Szrj   dfs_accessible_data *d = (dfs_accessible_data *)data;
73638fd1498Szrj   tree type = BINFO_TYPE (binfo);
73738fd1498Szrj   if (member_declared_in_type (d->decl, type))
73838fd1498Szrj     return dfs_skip_bases;
73938fd1498Szrj   return NULL_TREE;
74038fd1498Szrj }
74138fd1498Szrj 
74238fd1498Szrj /* Called via dfs_walk_once_accessible from accessible_p */
74338fd1498Szrj 
74438fd1498Szrj static tree
dfs_accessible_post(tree binfo,void * data)74538fd1498Szrj dfs_accessible_post (tree binfo, void *data)
74638fd1498Szrj {
74738fd1498Szrj   /* access_in_type already set BINFO_ACCESS for us.  */
74838fd1498Szrj   access_kind access = BINFO_ACCESS (binfo);
74938fd1498Szrj   tree N = BINFO_TYPE (binfo);
75038fd1498Szrj   dfs_accessible_data *d = (dfs_accessible_data *)data;
75138fd1498Szrj   tree decl = d->decl;
75238fd1498Szrj   tree scope = current_nonlambda_scope ();
75338fd1498Szrj 
75438fd1498Szrj   /* A member m is accessible at the point R when named in class N if */
75538fd1498Szrj   switch (access)
75638fd1498Szrj     {
75738fd1498Szrj     case ak_none:
75838fd1498Szrj       return NULL_TREE;
75938fd1498Szrj 
76038fd1498Szrj     case ak_public:
76138fd1498Szrj       /* m as a member of N is public, or */
76238fd1498Szrj       return binfo;
76338fd1498Szrj 
76438fd1498Szrj     case ak_private:
76538fd1498Szrj       {
76638fd1498Szrj 	/* m as a member of N is private, and R occurs in a member or friend of
76738fd1498Szrj 	   class N, or */
76838fd1498Szrj 	if (scope && TREE_CODE (scope) != NAMESPACE_DECL
76938fd1498Szrj 	    && is_friend (N, scope))
77038fd1498Szrj 	  return binfo;
77138fd1498Szrj 	return NULL_TREE;
77238fd1498Szrj       }
77338fd1498Szrj 
77438fd1498Szrj     case ak_protected:
77538fd1498Szrj       {
77638fd1498Szrj 	/* m as a member of N is protected, and R occurs in a member or friend
77738fd1498Szrj 	   of class N, or in a member or friend of a class P derived from N,
77838fd1498Szrj 	   where m as a member of P is public, private, or protected  */
77938fd1498Szrj 	if (friend_accessible_p (scope, decl, N, d->object_type))
78038fd1498Szrj 	  return binfo;
78138fd1498Szrj 	return NULL_TREE;
78238fd1498Szrj       }
78338fd1498Szrj 
78438fd1498Szrj     default:
78538fd1498Szrj       gcc_unreachable ();
78638fd1498Szrj     }
78738fd1498Szrj }
78838fd1498Szrj 
78938fd1498Szrj /* Like accessible_p below, but within a template returns true iff DECL is
79038fd1498Szrj    accessible in TYPE to all possible instantiations of the template.  */
79138fd1498Szrj 
79238fd1498Szrj int
accessible_in_template_p(tree type,tree decl)79338fd1498Szrj accessible_in_template_p (tree type, tree decl)
79438fd1498Szrj {
79538fd1498Szrj   int save_ptd = processing_template_decl;
79638fd1498Szrj   processing_template_decl = 0;
79738fd1498Szrj   int val = accessible_p (type, decl, false);
79838fd1498Szrj   processing_template_decl = save_ptd;
79938fd1498Szrj   return val;
80038fd1498Szrj }
80138fd1498Szrj 
80238fd1498Szrj /* DECL is a declaration from a base class of TYPE, which was the
80338fd1498Szrj    class used to name DECL.  Return nonzero if, in the current
80438fd1498Szrj    context, DECL is accessible.  If TYPE is actually a BINFO node,
80538fd1498Szrj    then we can tell in what context the access is occurring by looking
80638fd1498Szrj    at the most derived class along the path indicated by BINFO.  If
80738fd1498Szrj    CONSIDER_LOCAL is true, do consider special access the current
80838fd1498Szrj    scope or friendship thereof we might have.  */
80938fd1498Szrj 
81038fd1498Szrj int
accessible_p(tree type,tree decl,bool consider_local_p)81138fd1498Szrj accessible_p (tree type, tree decl, bool consider_local_p)
81238fd1498Szrj {
81338fd1498Szrj   tree binfo;
81438fd1498Szrj   access_kind access;
81538fd1498Szrj 
81638fd1498Szrj   /* If this declaration is in a block or namespace scope, there's no
81738fd1498Szrj      access control.  */
81838fd1498Szrj   if (!TYPE_P (context_for_name_lookup (decl)))
81938fd1498Szrj     return 1;
82038fd1498Szrj 
82138fd1498Szrj   /* There is no need to perform access checks inside a thunk.  */
82238fd1498Szrj   if (current_function_decl && DECL_THUNK_P (current_function_decl))
82338fd1498Szrj     return 1;
82438fd1498Szrj 
82538fd1498Szrj   /* In a template declaration, we cannot be sure whether the
82638fd1498Szrj      particular specialization that is instantiated will be a friend
82738fd1498Szrj      or not.  Therefore, all access checks are deferred until
82838fd1498Szrj      instantiation.  However, PROCESSING_TEMPLATE_DECL is set in the
82938fd1498Szrj      parameter list for a template (because we may see dependent types
83038fd1498Szrj      in default arguments for template parameters), and access
83138fd1498Szrj      checking should be performed in the outermost parameter list.  */
83238fd1498Szrj   if (processing_template_decl
83338fd1498Szrj       && !expanding_concept ()
83438fd1498Szrj       && (!processing_template_parmlist || processing_template_decl > 1))
83538fd1498Szrj     return 1;
83638fd1498Szrj 
83738fd1498Szrj   tree otype = NULL_TREE;
83838fd1498Szrj   if (!TYPE_P (type))
83938fd1498Szrj     {
84038fd1498Szrj       /* When accessing a non-static member, the most derived type in the
84138fd1498Szrj 	 binfo chain is the type of the object; remember that type for
84238fd1498Szrj 	 protected_accessible_p.  */
84338fd1498Szrj       for (tree b = type; b; b = BINFO_INHERITANCE_CHAIN (b))
84438fd1498Szrj 	otype = BINFO_TYPE (b);
84538fd1498Szrj       type = BINFO_TYPE (type);
84638fd1498Szrj     }
84738fd1498Szrj   else
84838fd1498Szrj     otype = type;
84938fd1498Szrj 
85038fd1498Szrj   /* [class.access.base]
85138fd1498Szrj 
85238fd1498Szrj      A member m is accessible when named in class N if
85338fd1498Szrj 
85438fd1498Szrj      --m as a member of N is public, or
85538fd1498Szrj 
85638fd1498Szrj      --m as a member of N is private, and the reference occurs in a
85738fd1498Szrj        member or friend of class N, or
85838fd1498Szrj 
85938fd1498Szrj      --m as a member of N is protected, and the reference occurs in a
86038fd1498Szrj        member or friend of class N, or in a member or friend of a
86138fd1498Szrj        class P derived from N, where m as a member of P is public, private or
86238fd1498Szrj        protected, or
86338fd1498Szrj 
86438fd1498Szrj      --there exists a base class B of N that is accessible at the point
86538fd1498Szrj        of reference, and m is accessible when named in class B.
86638fd1498Szrj 
86738fd1498Szrj     We walk the base class hierarchy, checking these conditions.  */
86838fd1498Szrj 
86938fd1498Szrj   /* We walk using TYPE_BINFO (type) because access_in_type will set
87038fd1498Szrj      BINFO_ACCESS on it and its bases.  */
87138fd1498Szrj   binfo = TYPE_BINFO (type);
87238fd1498Szrj 
87338fd1498Szrj   /* Compute the accessibility of DECL in the class hierarchy
87438fd1498Szrj      dominated by type.  */
87538fd1498Szrj   access = access_in_type (type, decl);
87638fd1498Szrj   if (access == ak_public)
87738fd1498Szrj     return 1;
87838fd1498Szrj 
87938fd1498Szrj   /* If we aren't considering the point of reference, only the first bullet
88038fd1498Szrj      applies.  */
88138fd1498Szrj   if (!consider_local_p)
88238fd1498Szrj     return 0;
88338fd1498Szrj 
88438fd1498Szrj   dfs_accessible_data d = { decl, otype };
88538fd1498Szrj 
88638fd1498Szrj   /* Walk the hierarchy again, looking for a base class that allows
88738fd1498Szrj      access.  */
88838fd1498Szrj   return dfs_walk_once_accessible (binfo, /*friends=*/true,
88938fd1498Szrj 				   dfs_accessible_pre,
89038fd1498Szrj 				   dfs_accessible_post, &d)
89138fd1498Szrj     != NULL_TREE;
89238fd1498Szrj }
89338fd1498Szrj 
89438fd1498Szrj struct lookup_field_info {
89538fd1498Szrj   /* The type in which we're looking.  */
89638fd1498Szrj   tree type;
89738fd1498Szrj   /* The name of the field for which we're looking.  */
89838fd1498Szrj   tree name;
89938fd1498Szrj   /* If non-NULL, the current result of the lookup.  */
90038fd1498Szrj   tree rval;
90138fd1498Szrj   /* The path to RVAL.  */
90238fd1498Szrj   tree rval_binfo;
90338fd1498Szrj   /* If non-NULL, the lookup was ambiguous, and this is a list of the
90438fd1498Szrj      candidates.  */
90538fd1498Szrj   tree ambiguous;
90638fd1498Szrj   /* If nonzero, we are looking for types, not data members.  */
90738fd1498Szrj   int want_type;
90838fd1498Szrj   /* If something went wrong, a message indicating what.  */
90938fd1498Szrj   const char *errstr;
91038fd1498Szrj };
91138fd1498Szrj 
91238fd1498Szrj /* Nonzero for a class member means that it is shared between all objects
91338fd1498Szrj    of that class.
91438fd1498Szrj 
91538fd1498Szrj    [class.member.lookup]:If the resulting set of declarations are not all
91638fd1498Szrj    from sub-objects of the same type, or the set has a  nonstatic  member
91738fd1498Szrj    and  includes members from distinct sub-objects, there is an ambiguity
91838fd1498Szrj    and the program is ill-formed.
91938fd1498Szrj 
92038fd1498Szrj    This function checks that T contains no nonstatic members.  */
92138fd1498Szrj 
92238fd1498Szrj int
shared_member_p(tree t)92338fd1498Szrj shared_member_p (tree t)
92438fd1498Szrj {
92538fd1498Szrj   if (VAR_P (t) || TREE_CODE (t) == TYPE_DECL \
92638fd1498Szrj       || TREE_CODE (t) == CONST_DECL)
92738fd1498Szrj     return 1;
92838fd1498Szrj   if (is_overloaded_fn (t))
92938fd1498Szrj     {
93038fd1498Szrj       for (ovl_iterator iter (get_fns (t)); iter; ++iter)
93138fd1498Szrj 	if (DECL_NONSTATIC_MEMBER_FUNCTION_P (*iter))
93238fd1498Szrj 	  return 0;
93338fd1498Szrj       return 1;
93438fd1498Szrj     }
93538fd1498Szrj   return 0;
93638fd1498Szrj }
93738fd1498Szrj 
93838fd1498Szrj /* Routine to see if the sub-object denoted by the binfo PARENT can be
93938fd1498Szrj    found as a base class and sub-object of the object denoted by
94038fd1498Szrj    BINFO.  */
94138fd1498Szrj 
94238fd1498Szrj static int
is_subobject_of_p(tree parent,tree binfo)94338fd1498Szrj is_subobject_of_p (tree parent, tree binfo)
94438fd1498Szrj {
94538fd1498Szrj   tree probe;
94638fd1498Szrj 
94738fd1498Szrj   for (probe = parent; probe; probe = BINFO_INHERITANCE_CHAIN (probe))
94838fd1498Szrj     {
94938fd1498Szrj       if (probe == binfo)
95038fd1498Szrj 	return 1;
95138fd1498Szrj       if (BINFO_VIRTUAL_P (probe))
95238fd1498Szrj 	return (binfo_for_vbase (BINFO_TYPE (probe), BINFO_TYPE (binfo))
95338fd1498Szrj 		!= NULL_TREE);
95438fd1498Szrj     }
95538fd1498Szrj   return 0;
95638fd1498Szrj }
95738fd1498Szrj 
95838fd1498Szrj /* DATA is really a struct lookup_field_info.  Look for a field with
95938fd1498Szrj    the name indicated there in BINFO.  If this function returns a
96038fd1498Szrj    non-NULL value it is the result of the lookup.  Called from
96138fd1498Szrj    lookup_field via breadth_first_search.  */
96238fd1498Szrj 
96338fd1498Szrj static tree
lookup_field_r(tree binfo,void * data)96438fd1498Szrj lookup_field_r (tree binfo, void *data)
96538fd1498Szrj {
96638fd1498Szrj   struct lookup_field_info *lfi = (struct lookup_field_info *) data;
96738fd1498Szrj   tree type = BINFO_TYPE (binfo);
96838fd1498Szrj   tree nval = NULL_TREE;
96938fd1498Szrj 
97038fd1498Szrj   /* If this is a dependent base, don't look in it.  */
97138fd1498Szrj   if (BINFO_DEPENDENT_BASE_P (binfo))
97238fd1498Szrj     return NULL_TREE;
97338fd1498Szrj 
97438fd1498Szrj   /* If this base class is hidden by the best-known value so far, we
97538fd1498Szrj      don't need to look.  */
97638fd1498Szrj   if (lfi->rval_binfo && BINFO_INHERITANCE_CHAIN (binfo) == lfi->rval_binfo
97738fd1498Szrj       && !BINFO_VIRTUAL_P (binfo))
97838fd1498Szrj     return dfs_skip_bases;
97938fd1498Szrj 
98038fd1498Szrj   nval = get_class_binding (type, lfi->name, lfi->want_type);
98138fd1498Szrj 
98238fd1498Szrj   /* If we're looking up a type (as with an elaborated type specifier)
98338fd1498Szrj      we ignore all non-types we find.  */
98438fd1498Szrj   if (lfi->want_type && nval && !DECL_DECLARES_TYPE_P (nval))
98538fd1498Szrj     {
98638fd1498Szrj       nval = NULL_TREE;
98738fd1498Szrj       if (CLASSTYPE_NESTED_UTDS (type))
98838fd1498Szrj 	if (binding_entry e = binding_table_find (CLASSTYPE_NESTED_UTDS (type),
98938fd1498Szrj 						  lfi->name))
99038fd1498Szrj 	  nval = TYPE_MAIN_DECL (e->type);
99138fd1498Szrj     }
99238fd1498Szrj 
99338fd1498Szrj   /* If there is no declaration with the indicated name in this type,
99438fd1498Szrj      then there's nothing to do.  */
99538fd1498Szrj   if (!nval)
99638fd1498Szrj     goto done;
99738fd1498Szrj 
99838fd1498Szrj   /* If the lookup already found a match, and the new value doesn't
99938fd1498Szrj      hide the old one, we might have an ambiguity.  */
100038fd1498Szrj   if (lfi->rval_binfo
100138fd1498Szrj       && !is_subobject_of_p (lfi->rval_binfo, binfo))
100238fd1498Szrj 
100338fd1498Szrj     {
100438fd1498Szrj       if (nval == lfi->rval && shared_member_p (nval))
100538fd1498Szrj 	/* The two things are really the same.  */
100638fd1498Szrj 	;
100738fd1498Szrj       else if (is_subobject_of_p (binfo, lfi->rval_binfo))
100838fd1498Szrj 	/* The previous value hides the new one.  */
100938fd1498Szrj 	;
101038fd1498Szrj       else
101138fd1498Szrj 	{
101238fd1498Szrj 	  /* We have a real ambiguity.  We keep a chain of all the
101338fd1498Szrj 	     candidates.  */
101438fd1498Szrj 	  if (!lfi->ambiguous && lfi->rval)
101538fd1498Szrj 	    {
101638fd1498Szrj 	      /* This is the first time we noticed an ambiguity.  Add
101738fd1498Szrj 		 what we previously thought was a reasonable candidate
101838fd1498Szrj 		 to the list.  */
101938fd1498Szrj 	      lfi->ambiguous = tree_cons (NULL_TREE, lfi->rval, NULL_TREE);
102038fd1498Szrj 	      TREE_TYPE (lfi->ambiguous) = error_mark_node;
102138fd1498Szrj 	    }
102238fd1498Szrj 
102338fd1498Szrj 	  /* Add the new value.  */
102438fd1498Szrj 	  lfi->ambiguous = tree_cons (NULL_TREE, nval, lfi->ambiguous);
102538fd1498Szrj 	  TREE_TYPE (lfi->ambiguous) = error_mark_node;
102638fd1498Szrj 	  lfi->errstr = G_("request for member %qD is ambiguous");
102738fd1498Szrj 	}
102838fd1498Szrj     }
102938fd1498Szrj   else
103038fd1498Szrj     {
103138fd1498Szrj       lfi->rval = nval;
103238fd1498Szrj       lfi->rval_binfo = binfo;
103338fd1498Szrj     }
103438fd1498Szrj 
103538fd1498Szrj  done:
103638fd1498Szrj   /* Don't look for constructors or destructors in base classes.  */
103738fd1498Szrj   if (IDENTIFIER_CDTOR_P (lfi->name))
103838fd1498Szrj     return dfs_skip_bases;
103938fd1498Szrj   return NULL_TREE;
104038fd1498Szrj }
104138fd1498Szrj 
104238fd1498Szrj /* Return a "baselink" with BASELINK_BINFO, BASELINK_ACCESS_BINFO,
104338fd1498Szrj    BASELINK_FUNCTIONS, and BASELINK_OPTYPE set to BINFO, ACCESS_BINFO,
104438fd1498Szrj    FUNCTIONS, and OPTYPE respectively.  */
104538fd1498Szrj 
104638fd1498Szrj tree
build_baselink(tree binfo,tree access_binfo,tree functions,tree optype)104738fd1498Szrj build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
104838fd1498Szrj {
104938fd1498Szrj   tree baselink;
105038fd1498Szrj 
105138fd1498Szrj   gcc_assert (TREE_CODE (functions) == FUNCTION_DECL
105238fd1498Szrj 	      || TREE_CODE (functions) == TEMPLATE_DECL
105338fd1498Szrj 	      || TREE_CODE (functions) == TEMPLATE_ID_EXPR
105438fd1498Szrj 	      || TREE_CODE (functions) == OVERLOAD);
105538fd1498Szrj   gcc_assert (!optype || TYPE_P (optype));
105638fd1498Szrj   gcc_assert (TREE_TYPE (functions));
105738fd1498Szrj 
105838fd1498Szrj   baselink = make_node (BASELINK);
105938fd1498Szrj   TREE_TYPE (baselink) = TREE_TYPE (functions);
106038fd1498Szrj   BASELINK_BINFO (baselink) = binfo;
106138fd1498Szrj   BASELINK_ACCESS_BINFO (baselink) = access_binfo;
106238fd1498Szrj   BASELINK_FUNCTIONS (baselink) = functions;
106338fd1498Szrj   BASELINK_OPTYPE (baselink) = optype;
106438fd1498Szrj 
106538fd1498Szrj   return baselink;
106638fd1498Szrj }
106738fd1498Szrj 
106838fd1498Szrj /* Look for a member named NAME in an inheritance lattice dominated by
106938fd1498Szrj    XBASETYPE.  If PROTECT is 0 or two, we do not check access.  If it
107038fd1498Szrj    is 1, we enforce accessibility.  If PROTECT is zero, then, for an
107138fd1498Szrj    ambiguous lookup, we return NULL.  If PROTECT is 1, we issue error
107238fd1498Szrj    messages about inaccessible or ambiguous lookup.  If PROTECT is 2,
107338fd1498Szrj    we return a TREE_LIST whose TREE_TYPE is error_mark_node and whose
107438fd1498Szrj    TREE_VALUEs are the list of ambiguous candidates.
107538fd1498Szrj 
107638fd1498Szrj    WANT_TYPE is 1 when we should only return TYPE_DECLs.
107738fd1498Szrj 
107838fd1498Szrj    If nothing can be found return NULL_TREE and do not issue an error.
107938fd1498Szrj 
108038fd1498Szrj    If non-NULL, failure information is written back to AFI.  */
108138fd1498Szrj 
108238fd1498Szrj tree
lookup_member(tree xbasetype,tree name,int protect,bool want_type,tsubst_flags_t complain,access_failure_info * afi)108338fd1498Szrj lookup_member (tree xbasetype, tree name, int protect, bool want_type,
108438fd1498Szrj 	       tsubst_flags_t complain, access_failure_info *afi)
108538fd1498Szrj {
108638fd1498Szrj   tree rval, rval_binfo = NULL_TREE;
108738fd1498Szrj   tree type = NULL_TREE, basetype_path = NULL_TREE;
108838fd1498Szrj   struct lookup_field_info lfi;
108938fd1498Szrj 
109038fd1498Szrj   /* rval_binfo is the binfo associated with the found member, note,
109138fd1498Szrj      this can be set with useful information, even when rval is not
109238fd1498Szrj      set, because it must deal with ALL members, not just non-function
109338fd1498Szrj      members.  It is used for ambiguity checking and the hidden
109438fd1498Szrj      checks.  Whereas rval is only set if a proper (not hidden)
109538fd1498Szrj      non-function member is found.  */
109638fd1498Szrj 
109738fd1498Szrj   const char *errstr = 0;
109838fd1498Szrj 
109938fd1498Szrj   if (name == error_mark_node
110038fd1498Szrj       || xbasetype == NULL_TREE
110138fd1498Szrj       || xbasetype == error_mark_node)
110238fd1498Szrj     return NULL_TREE;
110338fd1498Szrj 
110438fd1498Szrj   gcc_assert (identifier_p (name));
110538fd1498Szrj 
110638fd1498Szrj   if (TREE_CODE (xbasetype) == TREE_BINFO)
110738fd1498Szrj     {
110838fd1498Szrj       type = BINFO_TYPE (xbasetype);
110938fd1498Szrj       basetype_path = xbasetype;
111038fd1498Szrj     }
111138fd1498Szrj   else
111238fd1498Szrj     {
111338fd1498Szrj       if (!RECORD_OR_UNION_CODE_P (TREE_CODE (xbasetype)))
111438fd1498Szrj 	return NULL_TREE;
111538fd1498Szrj       type = xbasetype;
111638fd1498Szrj       xbasetype = NULL_TREE;
111738fd1498Szrj     }
111838fd1498Szrj 
111938fd1498Szrj   type = complete_type (type);
112038fd1498Szrj 
112138fd1498Szrj   /* Make sure we're looking for a member of the current instantiation in the
112238fd1498Szrj      right partial specialization.  */
1123*58e805e6Szrj   if (dependent_type_p (type))
112438fd1498Szrj     if (tree t = currently_open_class (type))
112538fd1498Szrj       type = t;
112638fd1498Szrj 
112738fd1498Szrj   if (!basetype_path)
112838fd1498Szrj     basetype_path = TYPE_BINFO (type);
112938fd1498Szrj 
113038fd1498Szrj   if (!basetype_path)
113138fd1498Szrj     return NULL_TREE;
113238fd1498Szrj 
113338fd1498Szrj   memset (&lfi, 0, sizeof (lfi));
113438fd1498Szrj   lfi.type = type;
113538fd1498Szrj   lfi.name = name;
113638fd1498Szrj   lfi.want_type = want_type;
113738fd1498Szrj   dfs_walk_all (basetype_path, &lookup_field_r, NULL, &lfi);
113838fd1498Szrj   rval = lfi.rval;
113938fd1498Szrj   rval_binfo = lfi.rval_binfo;
114038fd1498Szrj   if (rval_binfo)
114138fd1498Szrj     type = BINFO_TYPE (rval_binfo);
114238fd1498Szrj   errstr = lfi.errstr;
114338fd1498Szrj 
114438fd1498Szrj   /* If we are not interested in ambiguities, don't report them;
114538fd1498Szrj      just return NULL_TREE.  */
114638fd1498Szrj   if (!protect && lfi.ambiguous)
114738fd1498Szrj     return NULL_TREE;
114838fd1498Szrj 
114938fd1498Szrj   if (protect == 2)
115038fd1498Szrj     {
115138fd1498Szrj       if (lfi.ambiguous)
115238fd1498Szrj 	return lfi.ambiguous;
115338fd1498Szrj       else
115438fd1498Szrj 	protect = 0;
115538fd1498Szrj     }
115638fd1498Szrj 
115738fd1498Szrj   /* [class.access]
115838fd1498Szrj 
115938fd1498Szrj      In the case of overloaded function names, access control is
116038fd1498Szrj      applied to the function selected by overloaded resolution.
116138fd1498Szrj 
116238fd1498Szrj      We cannot check here, even if RVAL is only a single non-static
116338fd1498Szrj      member function, since we do not know what the "this" pointer
116438fd1498Szrj      will be.  For:
116538fd1498Szrj 
116638fd1498Szrj         class A { protected: void f(); };
116738fd1498Szrj         class B : public A {
116838fd1498Szrj           void g(A *p) {
116938fd1498Szrj             f(); // OK
117038fd1498Szrj             p->f(); // Not OK.
117138fd1498Szrj           }
117238fd1498Szrj         };
117338fd1498Szrj 
117438fd1498Szrj     only the first call to "f" is valid.  However, if the function is
117538fd1498Szrj     static, we can check.  */
117638fd1498Szrj   if (rval && protect
117738fd1498Szrj       && !really_overloaded_fn (rval))
117838fd1498Szrj     {
117938fd1498Szrj       tree decl = is_overloaded_fn (rval) ? get_first_fn (rval) : rval;
118038fd1498Szrj       if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
118138fd1498Szrj 	  && !perform_or_defer_access_check (basetype_path, decl, decl,
118238fd1498Szrj 					     complain, afi))
118338fd1498Szrj 	rval = error_mark_node;
118438fd1498Szrj     }
118538fd1498Szrj 
118638fd1498Szrj   if (errstr && protect)
118738fd1498Szrj     {
118838fd1498Szrj       if (complain & tf_error)
118938fd1498Szrj 	{
119038fd1498Szrj 	  error (errstr, name, type);
119138fd1498Szrj 	  if (lfi.ambiguous)
119238fd1498Szrj 	    print_candidates (lfi.ambiguous);
119338fd1498Szrj 	}
119438fd1498Szrj       rval = error_mark_node;
119538fd1498Szrj     }
119638fd1498Szrj 
119738fd1498Szrj   if (rval && is_overloaded_fn (rval))
119838fd1498Szrj     rval = build_baselink (rval_binfo, basetype_path, rval,
119938fd1498Szrj 			   (IDENTIFIER_CONV_OP_P (name)
120038fd1498Szrj 			   ? TREE_TYPE (name): NULL_TREE));
120138fd1498Szrj   return rval;
120238fd1498Szrj }
120338fd1498Szrj 
120438fd1498Szrj /* Helper class for lookup_member_fuzzy.  */
120538fd1498Szrj 
120638fd1498Szrj class lookup_field_fuzzy_info
120738fd1498Szrj {
120838fd1498Szrj  public:
lookup_field_fuzzy_info(bool want_type_p)120938fd1498Szrj   lookup_field_fuzzy_info (bool want_type_p) :
121038fd1498Szrj     m_want_type_p (want_type_p), m_candidates () {}
121138fd1498Szrj 
121238fd1498Szrj   void fuzzy_lookup_field (tree type);
121338fd1498Szrj 
121438fd1498Szrj   /* If true, we are looking for types, not data members.  */
121538fd1498Szrj   bool m_want_type_p;
121638fd1498Szrj   /* The result: a vec of identifiers.  */
121738fd1498Szrj   auto_vec<tree> m_candidates;
121838fd1498Szrj };
121938fd1498Szrj 
122038fd1498Szrj /* Locate all fields within TYPE, append them to m_candidates.  */
122138fd1498Szrj 
122238fd1498Szrj void
fuzzy_lookup_field(tree type)122338fd1498Szrj lookup_field_fuzzy_info::fuzzy_lookup_field (tree type)
122438fd1498Szrj {
122538fd1498Szrj   if (!CLASS_TYPE_P (type))
122638fd1498Szrj     return;
122738fd1498Szrj 
122838fd1498Szrj   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
122938fd1498Szrj     {
1230*58e805e6Szrj       if (m_want_type_p && !DECL_DECLARES_TYPE_P (field))
1231*58e805e6Szrj 	continue;
1232*58e805e6Szrj 
1233*58e805e6Szrj       if (!DECL_NAME (field))
1234*58e805e6Szrj 	continue;
1235*58e805e6Szrj 
1236*58e805e6Szrj       if (is_lambda_ignored_entity (field))
1237*58e805e6Szrj 	continue;
1238*58e805e6Szrj 
123938fd1498Szrj       m_candidates.safe_push (DECL_NAME (field));
124038fd1498Szrj     }
124138fd1498Szrj }
124238fd1498Szrj 
124338fd1498Szrj 
124438fd1498Szrj /* Helper function for lookup_member_fuzzy, called via dfs_walk_all
124538fd1498Szrj    DATA is really a lookup_field_fuzzy_info.  Look for a field with
124638fd1498Szrj    the name indicated there in BINFO.  Gathers pertinent identifiers into
124738fd1498Szrj    m_candidates.  */
124838fd1498Szrj 
124938fd1498Szrj static tree
lookup_field_fuzzy_r(tree binfo,void * data)125038fd1498Szrj lookup_field_fuzzy_r (tree binfo, void *data)
125138fd1498Szrj {
125238fd1498Szrj   lookup_field_fuzzy_info *lffi = (lookup_field_fuzzy_info *) data;
125338fd1498Szrj   tree type = BINFO_TYPE (binfo);
125438fd1498Szrj 
125538fd1498Szrj   lffi->fuzzy_lookup_field (type);
125638fd1498Szrj 
125738fd1498Szrj   return NULL_TREE;
125838fd1498Szrj }
125938fd1498Szrj 
126038fd1498Szrj /* Like lookup_member, but try to find the closest match for NAME,
126138fd1498Szrj    rather than an exact match, and return an identifier (or NULL_TREE).
126238fd1498Szrj    Do not complain.  */
126338fd1498Szrj 
126438fd1498Szrj tree
lookup_member_fuzzy(tree xbasetype,tree name,bool want_type_p)126538fd1498Szrj lookup_member_fuzzy (tree xbasetype, tree name, bool want_type_p)
126638fd1498Szrj {
126738fd1498Szrj   tree type = NULL_TREE, basetype_path = NULL_TREE;
126838fd1498Szrj   struct lookup_field_fuzzy_info lffi (want_type_p);
126938fd1498Szrj 
127038fd1498Szrj   /* rval_binfo is the binfo associated with the found member, note,
127138fd1498Szrj      this can be set with useful information, even when rval is not
127238fd1498Szrj      set, because it must deal with ALL members, not just non-function
127338fd1498Szrj      members.  It is used for ambiguity checking and the hidden
127438fd1498Szrj      checks.  Whereas rval is only set if a proper (not hidden)
127538fd1498Szrj      non-function member is found.  */
127638fd1498Szrj 
127738fd1498Szrj   if (name == error_mark_node
127838fd1498Szrj       || xbasetype == NULL_TREE
127938fd1498Szrj       || xbasetype == error_mark_node)
128038fd1498Szrj     return NULL_TREE;
128138fd1498Szrj 
128238fd1498Szrj   gcc_assert (identifier_p (name));
128338fd1498Szrj 
128438fd1498Szrj   if (TREE_CODE (xbasetype) == TREE_BINFO)
128538fd1498Szrj     {
128638fd1498Szrj       type = BINFO_TYPE (xbasetype);
128738fd1498Szrj       basetype_path = xbasetype;
128838fd1498Szrj     }
128938fd1498Szrj   else
129038fd1498Szrj     {
129138fd1498Szrj       if (!RECORD_OR_UNION_CODE_P (TREE_CODE (xbasetype)))
129238fd1498Szrj 	return NULL_TREE;
129338fd1498Szrj       type = xbasetype;
129438fd1498Szrj       xbasetype = NULL_TREE;
129538fd1498Szrj     }
129638fd1498Szrj 
129738fd1498Szrj   type = complete_type (type);
129838fd1498Szrj 
129938fd1498Szrj   /* Make sure we're looking for a member of the current instantiation in the
130038fd1498Szrj      right partial specialization.  */
130138fd1498Szrj   if (flag_concepts && dependent_type_p (type))
130238fd1498Szrj     type = currently_open_class (type);
130338fd1498Szrj 
130438fd1498Szrj   if (!basetype_path)
130538fd1498Szrj     basetype_path = TYPE_BINFO (type);
130638fd1498Szrj 
130738fd1498Szrj   if (!basetype_path)
130838fd1498Szrj     return NULL_TREE;
130938fd1498Szrj 
131038fd1498Szrj   /* Populate lffi.m_candidates.  */
131138fd1498Szrj   dfs_walk_all (basetype_path, &lookup_field_fuzzy_r, NULL, &lffi);
131238fd1498Szrj 
131338fd1498Szrj   return find_closest_identifier (name, &lffi.m_candidates);
131438fd1498Szrj }
131538fd1498Szrj 
131638fd1498Szrj /* Like lookup_member, except that if we find a function member we
131738fd1498Szrj    return NULL_TREE.  */
131838fd1498Szrj 
131938fd1498Szrj tree
lookup_field(tree xbasetype,tree name,int protect,bool want_type)132038fd1498Szrj lookup_field (tree xbasetype, tree name, int protect, bool want_type)
132138fd1498Szrj {
132238fd1498Szrj   tree rval = lookup_member (xbasetype, name, protect, want_type,
132338fd1498Szrj 			     tf_warning_or_error);
132438fd1498Szrj 
132538fd1498Szrj   /* Ignore functions, but propagate the ambiguity list.  */
132638fd1498Szrj   if (!error_operand_p (rval)
132738fd1498Szrj       && (rval && BASELINK_P (rval)))
132838fd1498Szrj     return NULL_TREE;
132938fd1498Szrj 
133038fd1498Szrj   return rval;
133138fd1498Szrj }
133238fd1498Szrj 
133338fd1498Szrj /* Like lookup_member, except that if we find a non-function member we
133438fd1498Szrj    return NULL_TREE.  */
133538fd1498Szrj 
133638fd1498Szrj tree
lookup_fnfields(tree xbasetype,tree name,int protect)133738fd1498Szrj lookup_fnfields (tree xbasetype, tree name, int protect)
133838fd1498Szrj {
133938fd1498Szrj   tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false,
134038fd1498Szrj 			     tf_warning_or_error);
134138fd1498Szrj 
134238fd1498Szrj   /* Ignore non-functions, but propagate the ambiguity list.  */
134338fd1498Szrj   if (!error_operand_p (rval)
134438fd1498Szrj       && (rval && !BASELINK_P (rval)))
134538fd1498Szrj     return NULL_TREE;
134638fd1498Szrj 
134738fd1498Szrj   return rval;
134838fd1498Szrj }
134938fd1498Szrj 
135038fd1498Szrj /* DECL is the result of a qualified name lookup.  QUALIFYING_SCOPE is
135138fd1498Szrj    the class or namespace used to qualify the name.  CONTEXT_CLASS is
135238fd1498Szrj    the class corresponding to the object in which DECL will be used.
135338fd1498Szrj    Return a possibly modified version of DECL that takes into account
135438fd1498Szrj    the CONTEXT_CLASS.
135538fd1498Szrj 
135638fd1498Szrj    In particular, consider an expression like `B::m' in the context of
135738fd1498Szrj    a derived class `D'.  If `B::m' has been resolved to a BASELINK,
135838fd1498Szrj    then the most derived class indicated by the BASELINK_BINFO will be
135938fd1498Szrj    `B', not `D'.  This function makes that adjustment.  */
136038fd1498Szrj 
136138fd1498Szrj tree
adjust_result_of_qualified_name_lookup(tree decl,tree qualifying_scope,tree context_class)136238fd1498Szrj adjust_result_of_qualified_name_lookup (tree decl,
136338fd1498Szrj 					tree qualifying_scope,
136438fd1498Szrj 					tree context_class)
136538fd1498Szrj {
136638fd1498Szrj   if (context_class && context_class != error_mark_node
136738fd1498Szrj       && CLASS_TYPE_P (context_class)
136838fd1498Szrj       && CLASS_TYPE_P (qualifying_scope)
136938fd1498Szrj       && DERIVED_FROM_P (qualifying_scope, context_class)
137038fd1498Szrj       && BASELINK_P (decl))
137138fd1498Szrj     {
137238fd1498Szrj       tree base;
137338fd1498Szrj 
137438fd1498Szrj       /* Look for the QUALIFYING_SCOPE as a base of the CONTEXT_CLASS.
137538fd1498Szrj 	 Because we do not yet know which function will be chosen by
137638fd1498Szrj 	 overload resolution, we cannot yet check either accessibility
137738fd1498Szrj 	 or ambiguity -- in either case, the choice of a static member
137838fd1498Szrj 	 function might make the usage valid.  */
137938fd1498Szrj       base = lookup_base (context_class, qualifying_scope,
138038fd1498Szrj 			  ba_unique, NULL, tf_none);
138138fd1498Szrj       if (base && base != error_mark_node)
138238fd1498Szrj 	{
138338fd1498Szrj 	  BASELINK_ACCESS_BINFO (decl) = base;
138438fd1498Szrj 	  tree decl_binfo
138538fd1498Szrj 	    = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
138638fd1498Szrj 			   ba_unique, NULL, tf_none);
138738fd1498Szrj 	  if (decl_binfo && decl_binfo != error_mark_node)
138838fd1498Szrj 	    BASELINK_BINFO (decl) = decl_binfo;
138938fd1498Szrj 	}
139038fd1498Szrj     }
139138fd1498Szrj 
139238fd1498Szrj   if (BASELINK_P (decl))
139338fd1498Szrj     BASELINK_QUALIFIED_P (decl) = true;
139438fd1498Szrj 
139538fd1498Szrj   return decl;
139638fd1498Szrj }
139738fd1498Szrj 
139838fd1498Szrj 
139938fd1498Szrj /* Walk the class hierarchy within BINFO, in a depth-first traversal.
140038fd1498Szrj    PRE_FN is called in preorder, while POST_FN is called in postorder.
140138fd1498Szrj    If PRE_FN returns DFS_SKIP_BASES, child binfos will not be
140238fd1498Szrj    walked.  If PRE_FN or POST_FN returns a different non-NULL value,
140338fd1498Szrj    that value is immediately returned and the walk is terminated.  One
140438fd1498Szrj    of PRE_FN and POST_FN can be NULL.  At each node, PRE_FN and
140538fd1498Szrj    POST_FN are passed the binfo to examine and the caller's DATA
140638fd1498Szrj    value.  All paths are walked, thus virtual and morally virtual
140738fd1498Szrj    binfos can be multiply walked.  */
140838fd1498Szrj 
140938fd1498Szrj tree
dfs_walk_all(tree binfo,tree (* pre_fn)(tree,void *),tree (* post_fn)(tree,void *),void * data)141038fd1498Szrj dfs_walk_all (tree binfo, tree (*pre_fn) (tree, void *),
141138fd1498Szrj 	      tree (*post_fn) (tree, void *), void *data)
141238fd1498Szrj {
141338fd1498Szrj   tree rval;
141438fd1498Szrj   unsigned ix;
141538fd1498Szrj   tree base_binfo;
141638fd1498Szrj 
141738fd1498Szrj   /* Call the pre-order walking function.  */
141838fd1498Szrj   if (pre_fn)
141938fd1498Szrj     {
142038fd1498Szrj       rval = pre_fn (binfo, data);
142138fd1498Szrj       if (rval)
142238fd1498Szrj 	{
142338fd1498Szrj 	  if (rval == dfs_skip_bases)
142438fd1498Szrj 	    goto skip_bases;
142538fd1498Szrj 	  return rval;
142638fd1498Szrj 	}
142738fd1498Szrj     }
142838fd1498Szrj 
142938fd1498Szrj   /* Find the next child binfo to walk.  */
143038fd1498Szrj   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
143138fd1498Szrj     {
143238fd1498Szrj       rval = dfs_walk_all (base_binfo, pre_fn, post_fn, data);
143338fd1498Szrj       if (rval)
143438fd1498Szrj 	return rval;
143538fd1498Szrj     }
143638fd1498Szrj 
143738fd1498Szrj  skip_bases:
143838fd1498Szrj   /* Call the post-order walking function.  */
143938fd1498Szrj   if (post_fn)
144038fd1498Szrj     {
144138fd1498Szrj       rval = post_fn (binfo, data);
144238fd1498Szrj       gcc_assert (rval != dfs_skip_bases);
144338fd1498Szrj       return rval;
144438fd1498Szrj     }
144538fd1498Szrj 
144638fd1498Szrj   return NULL_TREE;
144738fd1498Szrj }
144838fd1498Szrj 
144938fd1498Szrj /* Worker for dfs_walk_once.  This behaves as dfs_walk_all, except
145038fd1498Szrj    that binfos are walked at most once.  */
145138fd1498Szrj 
145238fd1498Szrj static tree
dfs_walk_once_r(tree binfo,tree (* pre_fn)(tree,void *),tree (* post_fn)(tree,void *),hash_set<tree> * pset,void * data)145338fd1498Szrj dfs_walk_once_r (tree binfo, tree (*pre_fn) (tree, void *),
145438fd1498Szrj 		 tree (*post_fn) (tree, void *), hash_set<tree> *pset,
145538fd1498Szrj 		 void *data)
145638fd1498Szrj {
145738fd1498Szrj   tree rval;
145838fd1498Szrj   unsigned ix;
145938fd1498Szrj   tree base_binfo;
146038fd1498Szrj 
146138fd1498Szrj   /* Call the pre-order walking function.  */
146238fd1498Szrj   if (pre_fn)
146338fd1498Szrj     {
146438fd1498Szrj       rval = pre_fn (binfo, data);
146538fd1498Szrj       if (rval)
146638fd1498Szrj 	{
146738fd1498Szrj 	  if (rval == dfs_skip_bases)
146838fd1498Szrj 	    goto skip_bases;
146938fd1498Szrj 
147038fd1498Szrj 	  return rval;
147138fd1498Szrj 	}
147238fd1498Szrj     }
147338fd1498Szrj 
147438fd1498Szrj   /* Find the next child binfo to walk.  */
147538fd1498Szrj   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
147638fd1498Szrj     {
147738fd1498Szrj       if (BINFO_VIRTUAL_P (base_binfo))
147838fd1498Szrj 	if (pset->add (base_binfo))
147938fd1498Szrj 	  continue;
148038fd1498Szrj 
148138fd1498Szrj       rval = dfs_walk_once_r (base_binfo, pre_fn, post_fn, pset, data);
148238fd1498Szrj       if (rval)
148338fd1498Szrj 	return rval;
148438fd1498Szrj     }
148538fd1498Szrj 
148638fd1498Szrj  skip_bases:
148738fd1498Szrj   /* Call the post-order walking function.  */
148838fd1498Szrj   if (post_fn)
148938fd1498Szrj     {
149038fd1498Szrj       rval = post_fn (binfo, data);
149138fd1498Szrj       gcc_assert (rval != dfs_skip_bases);
149238fd1498Szrj       return rval;
149338fd1498Szrj     }
149438fd1498Szrj 
149538fd1498Szrj   return NULL_TREE;
149638fd1498Szrj }
149738fd1498Szrj 
149838fd1498Szrj /* Like dfs_walk_all, except that binfos are not multiply walked.  For
149938fd1498Szrj    non-diamond shaped hierarchies this is the same as dfs_walk_all.
150038fd1498Szrj    For diamond shaped hierarchies we must mark the virtual bases, to
150138fd1498Szrj    avoid multiple walks.  */
150238fd1498Szrj 
150338fd1498Szrj tree
dfs_walk_once(tree binfo,tree (* pre_fn)(tree,void *),tree (* post_fn)(tree,void *),void * data)150438fd1498Szrj dfs_walk_once (tree binfo, tree (*pre_fn) (tree, void *),
150538fd1498Szrj 	       tree (*post_fn) (tree, void *), void *data)
150638fd1498Szrj {
150738fd1498Szrj   static int active = 0;  /* We must not be called recursively. */
150838fd1498Szrj   tree rval;
150938fd1498Szrj 
151038fd1498Szrj   gcc_assert (pre_fn || post_fn);
151138fd1498Szrj   gcc_assert (!active);
151238fd1498Szrj   active++;
151338fd1498Szrj 
151438fd1498Szrj   if (!CLASSTYPE_DIAMOND_SHAPED_P (BINFO_TYPE (binfo)))
151538fd1498Szrj     /* We are not diamond shaped, and therefore cannot encounter the
151638fd1498Szrj        same binfo twice.  */
151738fd1498Szrj     rval = dfs_walk_all (binfo, pre_fn, post_fn, data);
151838fd1498Szrj   else
151938fd1498Szrj     {
152038fd1498Szrj       hash_set<tree> pset;
152138fd1498Szrj       rval = dfs_walk_once_r (binfo, pre_fn, post_fn, &pset, data);
152238fd1498Szrj     }
152338fd1498Szrj 
152438fd1498Szrj   active--;
152538fd1498Szrj 
152638fd1498Szrj   return rval;
152738fd1498Szrj }
152838fd1498Szrj 
152938fd1498Szrj /* Worker function for dfs_walk_once_accessible.  Behaves like
153038fd1498Szrj    dfs_walk_once_r, except (a) FRIENDS_P is true if special
153138fd1498Szrj    access given by the current context should be considered, (b) ONCE
153238fd1498Szrj    indicates whether bases should be marked during traversal.  */
153338fd1498Szrj 
153438fd1498Szrj static tree
dfs_walk_once_accessible_r(tree binfo,bool friends_p,hash_set<tree> * pset,tree (* pre_fn)(tree,void *),tree (* post_fn)(tree,void *),void * data)153538fd1498Szrj dfs_walk_once_accessible_r (tree binfo, bool friends_p, hash_set<tree> *pset,
153638fd1498Szrj 			    tree (*pre_fn) (tree, void *),
153738fd1498Szrj 			    tree (*post_fn) (tree, void *), void *data)
153838fd1498Szrj {
153938fd1498Szrj   tree rval = NULL_TREE;
154038fd1498Szrj   unsigned ix;
154138fd1498Szrj   tree base_binfo;
154238fd1498Szrj 
154338fd1498Szrj   /* Call the pre-order walking function.  */
154438fd1498Szrj   if (pre_fn)
154538fd1498Szrj     {
154638fd1498Szrj       rval = pre_fn (binfo, data);
154738fd1498Szrj       if (rval)
154838fd1498Szrj 	{
154938fd1498Szrj 	  if (rval == dfs_skip_bases)
155038fd1498Szrj 	    goto skip_bases;
155138fd1498Szrj 
155238fd1498Szrj 	  return rval;
155338fd1498Szrj 	}
155438fd1498Szrj     }
155538fd1498Szrj 
155638fd1498Szrj   /* Find the next child binfo to walk.  */
155738fd1498Szrj   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
155838fd1498Szrj     {
155938fd1498Szrj       bool mark = pset && BINFO_VIRTUAL_P (base_binfo);
156038fd1498Szrj 
156138fd1498Szrj       if (mark && pset->contains (base_binfo))
156238fd1498Szrj 	continue;
156338fd1498Szrj 
156438fd1498Szrj       /* If the base is inherited via private or protected
156538fd1498Szrj 	 inheritance, then we can't see it, unless we are a friend of
156638fd1498Szrj 	 the current binfo.  */
156738fd1498Szrj       if (BINFO_BASE_ACCESS (binfo, ix) != access_public_node)
156838fd1498Szrj 	{
156938fd1498Szrj 	  tree scope;
157038fd1498Szrj 	  if (!friends_p)
157138fd1498Szrj 	    continue;
157238fd1498Szrj 	  scope = current_scope ();
157338fd1498Szrj 	  if (!scope
157438fd1498Szrj 	      || TREE_CODE (scope) == NAMESPACE_DECL
157538fd1498Szrj 	      || !is_friend (BINFO_TYPE (binfo), scope))
157638fd1498Szrj 	    continue;
157738fd1498Szrj 	}
157838fd1498Szrj 
157938fd1498Szrj       if (mark)
158038fd1498Szrj 	pset->add (base_binfo);
158138fd1498Szrj 
158238fd1498Szrj       rval = dfs_walk_once_accessible_r (base_binfo, friends_p, pset,
158338fd1498Szrj 					 pre_fn, post_fn, data);
158438fd1498Szrj       if (rval)
158538fd1498Szrj 	return rval;
158638fd1498Szrj     }
158738fd1498Szrj 
158838fd1498Szrj  skip_bases:
158938fd1498Szrj   /* Call the post-order walking function.  */
159038fd1498Szrj   if (post_fn)
159138fd1498Szrj     {
159238fd1498Szrj       rval = post_fn (binfo, data);
159338fd1498Szrj       gcc_assert (rval != dfs_skip_bases);
159438fd1498Szrj       return rval;
159538fd1498Szrj     }
159638fd1498Szrj 
159738fd1498Szrj   return NULL_TREE;
159838fd1498Szrj }
159938fd1498Szrj 
160038fd1498Szrj /* Like dfs_walk_once except that only accessible bases are walked.
160138fd1498Szrj    FRIENDS_P indicates whether friendship of the local context
160238fd1498Szrj    should be considered when determining accessibility.  */
160338fd1498Szrj 
160438fd1498Szrj static tree
dfs_walk_once_accessible(tree binfo,bool friends_p,tree (* pre_fn)(tree,void *),tree (* post_fn)(tree,void *),void * data)160538fd1498Szrj dfs_walk_once_accessible (tree binfo, bool friends_p,
160638fd1498Szrj 			    tree (*pre_fn) (tree, void *),
160738fd1498Szrj 			    tree (*post_fn) (tree, void *), void *data)
160838fd1498Szrj {
160938fd1498Szrj   hash_set<tree> *pset = NULL;
161038fd1498Szrj   if (CLASSTYPE_DIAMOND_SHAPED_P (BINFO_TYPE (binfo)))
161138fd1498Szrj     pset = new hash_set<tree>;
161238fd1498Szrj   tree rval = dfs_walk_once_accessible_r (binfo, friends_p, pset,
161338fd1498Szrj 					  pre_fn, post_fn, data);
161438fd1498Szrj 
161538fd1498Szrj   if (pset)
161638fd1498Szrj     delete pset;
161738fd1498Szrj   return rval;
161838fd1498Szrj }
161938fd1498Szrj 
162038fd1498Szrj /* Return true iff the code of T is CODE, and it has compatible
162138fd1498Szrj    type with TYPE.  */
162238fd1498Szrj 
162338fd1498Szrj static bool
matches_code_and_type_p(tree t,enum tree_code code,tree type)162438fd1498Szrj matches_code_and_type_p (tree t, enum tree_code code, tree type)
162538fd1498Szrj {
162638fd1498Szrj   if (TREE_CODE (t) != code)
162738fd1498Szrj     return false;
162838fd1498Szrj   if (!cxx_types_compatible_p (TREE_TYPE (t), type))
162938fd1498Szrj     return false;
163038fd1498Szrj   return true;
163138fd1498Szrj }
163238fd1498Szrj 
163338fd1498Szrj /* Subroutine of direct_accessor_p and reference_accessor_p.
163438fd1498Szrj    Determine if COMPONENT_REF is a simple field lookup of this->FIELD_DECL.
163538fd1498Szrj    We expect a tree of the form:
163638fd1498Szrj 	     <component_ref:
163738fd1498Szrj 	       <indirect_ref:S>
163838fd1498Szrj 		 <nop_expr:P*
163938fd1498Szrj 		   <parm_decl (this)>
164038fd1498Szrj 		 <field_decl (FIELD_DECL)>>>.  */
164138fd1498Szrj 
164238fd1498Szrj static bool
field_access_p(tree component_ref,tree field_decl,tree field_type)164338fd1498Szrj field_access_p (tree component_ref, tree field_decl, tree field_type)
164438fd1498Szrj {
164538fd1498Szrj   if (!matches_code_and_type_p (component_ref, COMPONENT_REF, field_type))
164638fd1498Szrj     return false;
164738fd1498Szrj 
164838fd1498Szrj   tree indirect_ref = TREE_OPERAND (component_ref, 0);
164938fd1498Szrj   if (!INDIRECT_REF_P (indirect_ref))
165038fd1498Szrj     return false;
165138fd1498Szrj 
165238fd1498Szrj   tree ptr = STRIP_NOPS (TREE_OPERAND (indirect_ref, 0));
165338fd1498Szrj   if (!is_this_parameter (ptr))
165438fd1498Szrj     return false;
165538fd1498Szrj 
165638fd1498Szrj   /* Must access the correct field.  */
165738fd1498Szrj   if (TREE_OPERAND (component_ref, 1) != field_decl)
165838fd1498Szrj     return false;
165938fd1498Szrj   return true;
166038fd1498Szrj }
166138fd1498Szrj 
166238fd1498Szrj /* Subroutine of field_accessor_p.
166338fd1498Szrj 
166438fd1498Szrj    Assuming that INIT_EXPR has already had its code and type checked,
166538fd1498Szrj    determine if it is a simple accessor for FIELD_DECL
166638fd1498Szrj    (of type FIELD_TYPE).
166738fd1498Szrj 
166838fd1498Szrj    Specifically, a simple accessor within struct S of the form:
166938fd1498Szrj        T get_field () { return m_field; }
167038fd1498Szrj    should have a constexpr_fn_retval (saved_tree) of the form:
167138fd1498Szrj 	 <init_expr:T
167238fd1498Szrj 	   <result_decl:T
167338fd1498Szrj 	   <nop_expr:T
167438fd1498Szrj 	     <component_ref:
167538fd1498Szrj 	       <indirect_ref:S>
167638fd1498Szrj 		 <nop_expr:P*
167738fd1498Szrj 		   <parm_decl (this)>
167838fd1498Szrj 		 <field_decl (FIELD_DECL)>>>>>.  */
167938fd1498Szrj 
168038fd1498Szrj static bool
direct_accessor_p(tree init_expr,tree field_decl,tree field_type)168138fd1498Szrj direct_accessor_p (tree init_expr, tree field_decl, tree field_type)
168238fd1498Szrj {
168338fd1498Szrj   tree result_decl = TREE_OPERAND (init_expr, 0);
168438fd1498Szrj   if (!matches_code_and_type_p (result_decl, RESULT_DECL, field_type))
168538fd1498Szrj     return false;
168638fd1498Szrj 
168738fd1498Szrj   tree component_ref = STRIP_NOPS (TREE_OPERAND (init_expr, 1));
168838fd1498Szrj   if (!field_access_p (component_ref, field_decl, field_type))
168938fd1498Szrj     return false;
169038fd1498Szrj 
169138fd1498Szrj   return true;
169238fd1498Szrj }
169338fd1498Szrj 
169438fd1498Szrj /* Subroutine of field_accessor_p.
169538fd1498Szrj 
169638fd1498Szrj    Assuming that INIT_EXPR has already had its code and type checked,
169738fd1498Szrj    determine if it is a "reference" accessor for FIELD_DECL
169838fd1498Szrj    (of type FIELD_REFERENCE_TYPE).
169938fd1498Szrj 
170038fd1498Szrj    Specifically, a simple accessor within struct S of the form:
170138fd1498Szrj        T& get_field () { return m_field; }
170238fd1498Szrj    should have a constexpr_fn_retval (saved_tree) of the form:
170338fd1498Szrj 	 <init_expr:T&
170438fd1498Szrj 	   <result_decl:T&
170538fd1498Szrj 	   <nop_expr: T&
170638fd1498Szrj 	     <addr_expr: T*
170738fd1498Szrj 	       <component_ref:T
170838fd1498Szrj 		 <indirect_ref:S
170938fd1498Szrj 		   <nop_expr
171038fd1498Szrj 		     <parm_decl (this)>>
171138fd1498Szrj 		   <field (FIELD_DECL)>>>>>>.  */
171238fd1498Szrj static bool
reference_accessor_p(tree init_expr,tree field_decl,tree field_type,tree field_reference_type)171338fd1498Szrj reference_accessor_p (tree init_expr, tree field_decl, tree field_type,
171438fd1498Szrj 		      tree field_reference_type)
171538fd1498Szrj {
171638fd1498Szrj   tree result_decl = TREE_OPERAND (init_expr, 0);
171738fd1498Szrj   if (!matches_code_and_type_p (result_decl, RESULT_DECL, field_reference_type))
171838fd1498Szrj     return false;
171938fd1498Szrj 
172038fd1498Szrj   tree field_pointer_type = build_pointer_type (field_type);
172138fd1498Szrj   tree addr_expr = STRIP_NOPS (TREE_OPERAND (init_expr, 1));
172238fd1498Szrj   if (!matches_code_and_type_p (addr_expr, ADDR_EXPR, field_pointer_type))
172338fd1498Szrj     return false;
172438fd1498Szrj 
172538fd1498Szrj   tree component_ref = STRIP_NOPS (TREE_OPERAND (addr_expr, 0));
172638fd1498Szrj 
172738fd1498Szrj   if (!field_access_p (component_ref, field_decl, field_type))
172838fd1498Szrj     return false;
172938fd1498Szrj 
173038fd1498Szrj   return true;
173138fd1498Szrj }
173238fd1498Szrj 
173338fd1498Szrj /* Return true if FN is an accessor method for FIELD_DECL.
173438fd1498Szrj    i.e. a method of the form { return FIELD; }, with no
173538fd1498Szrj    conversions.
173638fd1498Szrj 
173738fd1498Szrj    If CONST_P, then additionally require that FN be a const
173838fd1498Szrj    method.  */
173938fd1498Szrj 
174038fd1498Szrj static bool
field_accessor_p(tree fn,tree field_decl,bool const_p)174138fd1498Szrj field_accessor_p (tree fn, tree field_decl, bool const_p)
174238fd1498Szrj {
174338fd1498Szrj   if (TREE_CODE (fn) != FUNCTION_DECL)
174438fd1498Szrj     return false;
174538fd1498Szrj 
174638fd1498Szrj   /* We don't yet support looking up static data, just fields.  */
174738fd1498Szrj   if (TREE_CODE (field_decl) != FIELD_DECL)
174838fd1498Szrj     return false;
174938fd1498Szrj 
175038fd1498Szrj   tree fntype = TREE_TYPE (fn);
175138fd1498Szrj   if (TREE_CODE (fntype) != METHOD_TYPE)
175238fd1498Szrj     return false;
175338fd1498Szrj 
175438fd1498Szrj   /* If the field is accessed via a const "this" argument, verify
175538fd1498Szrj      that the "this" parameter is const.  */
175638fd1498Szrj   if (const_p)
175738fd1498Szrj     {
175838fd1498Szrj       tree this_class = class_of_this_parm (fntype);
175938fd1498Szrj       if (!TYPE_READONLY (this_class))
176038fd1498Szrj 	return false;
176138fd1498Szrj     }
176238fd1498Szrj 
176338fd1498Szrj   tree saved_tree = DECL_SAVED_TREE (fn);
176438fd1498Szrj 
176538fd1498Szrj   if (saved_tree == NULL_TREE)
176638fd1498Szrj     return false;
176738fd1498Szrj 
176838fd1498Szrj   /* Attempt to extract a single return value from the function,
176938fd1498Szrj      if it has one.  */
177038fd1498Szrj   tree retval = constexpr_fn_retval (saved_tree);
177138fd1498Szrj   if (retval == NULL_TREE || retval == error_mark_node)
177238fd1498Szrj     return false;
177338fd1498Szrj   /* Require an INIT_EXPR.  */
177438fd1498Szrj   if (TREE_CODE (retval) != INIT_EXPR)
177538fd1498Szrj     return false;
177638fd1498Szrj   tree init_expr = retval;
177738fd1498Szrj 
177838fd1498Szrj   /* Determine if this is a simple accessor within struct S of the form:
177938fd1498Szrj        T get_field () { return m_field; }.  */
178038fd1498Szrj   tree field_type = TREE_TYPE (field_decl);
178138fd1498Szrj   if (cxx_types_compatible_p (TREE_TYPE (init_expr), field_type))
178238fd1498Szrj     return direct_accessor_p (init_expr, field_decl, field_type);
178338fd1498Szrj 
178438fd1498Szrj   /* Failing that, determine if it is an accessor of the form:
178538fd1498Szrj        T& get_field () { return m_field; }.  */
178638fd1498Szrj   tree field_reference_type = cp_build_reference_type (field_type, false);
178738fd1498Szrj   if (cxx_types_compatible_p (TREE_TYPE (init_expr), field_reference_type))
178838fd1498Szrj     return reference_accessor_p (init_expr, field_decl, field_type,
178938fd1498Szrj 				 field_reference_type);
179038fd1498Szrj 
179138fd1498Szrj   return false;
179238fd1498Szrj }
179338fd1498Szrj 
179438fd1498Szrj /* Callback data for dfs_locate_field_accessor_pre.  */
179538fd1498Szrj 
179638fd1498Szrj struct locate_field_data
179738fd1498Szrj {
locate_field_datalocate_field_data179838fd1498Szrj   locate_field_data (tree field_decl_, bool const_p_)
179938fd1498Szrj   : field_decl (field_decl_), const_p (const_p_) {}
180038fd1498Szrj 
180138fd1498Szrj   tree field_decl;
180238fd1498Szrj   bool const_p;
180338fd1498Szrj };
180438fd1498Szrj 
180538fd1498Szrj /* Return a FUNCTION_DECL that is an "accessor" method for DATA, a FIELD_DECL,
180638fd1498Szrj    callable via binfo, if one exists, otherwise return NULL_TREE.
180738fd1498Szrj 
180838fd1498Szrj    Callback for dfs_walk_once_accessible for use within
180938fd1498Szrj    locate_field_accessor.  */
181038fd1498Szrj 
181138fd1498Szrj static tree
dfs_locate_field_accessor_pre(tree binfo,void * data)181238fd1498Szrj dfs_locate_field_accessor_pre (tree binfo, void *data)
181338fd1498Szrj {
181438fd1498Szrj   locate_field_data *lfd = (locate_field_data *)data;
181538fd1498Szrj   tree type = BINFO_TYPE (binfo);
181638fd1498Szrj 
181738fd1498Szrj   vec<tree, va_gc> *member_vec;
181838fd1498Szrj   tree fn;
181938fd1498Szrj   size_t i;
182038fd1498Szrj 
182138fd1498Szrj   if (!CLASS_TYPE_P (type))
182238fd1498Szrj     return NULL_TREE;
182338fd1498Szrj 
182438fd1498Szrj   member_vec = CLASSTYPE_MEMBER_VEC (type);
182538fd1498Szrj   if (!member_vec)
182638fd1498Szrj     return NULL_TREE;
182738fd1498Szrj 
182838fd1498Szrj   for (i = 0; vec_safe_iterate (member_vec, i, &fn); ++i)
182938fd1498Szrj     if (fn)
183038fd1498Szrj       if (field_accessor_p (fn, lfd->field_decl, lfd->const_p))
183138fd1498Szrj 	return fn;
183238fd1498Szrj 
183338fd1498Szrj   return NULL_TREE;
183438fd1498Szrj }
183538fd1498Szrj 
183638fd1498Szrj /* Return a FUNCTION_DECL that is an "accessor" method for FIELD_DECL,
183738fd1498Szrj    callable via BASETYPE_PATH, if one exists, otherwise return NULL_TREE.  */
183838fd1498Szrj 
183938fd1498Szrj tree
locate_field_accessor(tree basetype_path,tree field_decl,bool const_p)184038fd1498Szrj locate_field_accessor (tree basetype_path, tree field_decl, bool const_p)
184138fd1498Szrj {
184238fd1498Szrj   if (TREE_CODE (basetype_path) != TREE_BINFO)
184338fd1498Szrj     return NULL_TREE;
184438fd1498Szrj 
184538fd1498Szrj   /* Walk the hierarchy, looking for a method of some base class that allows
184638fd1498Szrj      access to the field.  */
184738fd1498Szrj   locate_field_data lfd (field_decl, const_p);
184838fd1498Szrj   return dfs_walk_once_accessible (basetype_path, /*friends=*/true,
184938fd1498Szrj 				   dfs_locate_field_accessor_pre,
185038fd1498Szrj 				   NULL, &lfd);
185138fd1498Szrj }
185238fd1498Szrj 
185338fd1498Szrj /* Check that virtual overrider OVERRIDER is acceptable for base function
185438fd1498Szrj    BASEFN. Issue diagnostic, and return zero, if unacceptable.  */
185538fd1498Szrj 
185638fd1498Szrj static int
check_final_overrider(tree overrider,tree basefn)185738fd1498Szrj check_final_overrider (tree overrider, tree basefn)
185838fd1498Szrj {
185938fd1498Szrj   tree over_type = TREE_TYPE (overrider);
186038fd1498Szrj   tree base_type = TREE_TYPE (basefn);
186138fd1498Szrj   tree over_return = fndecl_declared_return_type (overrider);
186238fd1498Szrj   tree base_return = fndecl_declared_return_type (basefn);
186338fd1498Szrj   tree over_throw, base_throw;
186438fd1498Szrj 
186538fd1498Szrj   int fail = 0;
186638fd1498Szrj 
186738fd1498Szrj   if (DECL_INVALID_OVERRIDER_P (overrider))
186838fd1498Szrj     return 0;
186938fd1498Szrj 
187038fd1498Szrj   if (same_type_p (base_return, over_return))
187138fd1498Szrj     /* OK */;
187238fd1498Szrj   else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
187338fd1498Szrj 	   || (TREE_CODE (base_return) == TREE_CODE (over_return)
187438fd1498Szrj 	       && POINTER_TYPE_P (base_return)))
187538fd1498Szrj     {
187638fd1498Szrj       /* Potentially covariant.  */
187738fd1498Szrj       unsigned base_quals, over_quals;
187838fd1498Szrj 
187938fd1498Szrj       fail = !POINTER_TYPE_P (base_return);
188038fd1498Szrj       if (!fail)
188138fd1498Szrj 	{
188238fd1498Szrj 	  fail = cp_type_quals (base_return) != cp_type_quals (over_return);
188338fd1498Szrj 
188438fd1498Szrj 	  base_return = TREE_TYPE (base_return);
188538fd1498Szrj 	  over_return = TREE_TYPE (over_return);
188638fd1498Szrj 	}
188738fd1498Szrj       base_quals = cp_type_quals (base_return);
188838fd1498Szrj       over_quals = cp_type_quals (over_return);
188938fd1498Szrj 
189038fd1498Szrj       if ((base_quals & over_quals) != over_quals)
189138fd1498Szrj 	fail = 1;
189238fd1498Szrj 
189338fd1498Szrj       if (CLASS_TYPE_P (base_return) && CLASS_TYPE_P (over_return))
189438fd1498Szrj 	{
189538fd1498Szrj 	  /* Strictly speaking, the standard requires the return type to be
189638fd1498Szrj 	     complete even if it only differs in cv-quals, but that seems
189738fd1498Szrj 	     like a bug in the wording.  */
189838fd1498Szrj 	  if (!same_type_ignoring_top_level_qualifiers_p (base_return,
189938fd1498Szrj 							  over_return))
190038fd1498Szrj 	    {
190138fd1498Szrj 	      tree binfo = lookup_base (over_return, base_return,
190238fd1498Szrj 					ba_check, NULL, tf_none);
190338fd1498Szrj 
190438fd1498Szrj 	      if (!binfo || binfo == error_mark_node)
190538fd1498Szrj 		fail = 1;
190638fd1498Szrj 	    }
190738fd1498Szrj 	}
190838fd1498Szrj       else if (can_convert_standard (TREE_TYPE (base_type),
190938fd1498Szrj 				     TREE_TYPE (over_type),
191038fd1498Szrj 				     tf_warning_or_error))
191138fd1498Szrj 	/* GNU extension, allow trivial pointer conversions such as
191238fd1498Szrj 	   converting to void *, or qualification conversion.  */
191338fd1498Szrj 	{
191438fd1498Szrj 	  if (pedwarn (DECL_SOURCE_LOCATION (overrider), 0,
191538fd1498Szrj 		       "invalid covariant return type for %q#D", overrider))
191638fd1498Szrj 	    inform (DECL_SOURCE_LOCATION (basefn),
191738fd1498Szrj 		    "overridden function is %q#D", basefn);
191838fd1498Szrj 	}
191938fd1498Szrj       else
192038fd1498Szrj 	fail = 2;
192138fd1498Szrj     }
192238fd1498Szrj   else
192338fd1498Szrj     fail = 2;
192438fd1498Szrj   if (!fail)
192538fd1498Szrj     /* OK */;
192638fd1498Szrj   else
192738fd1498Szrj     {
192838fd1498Szrj       if (fail == 1)
192938fd1498Szrj 	{
193038fd1498Szrj 	  error ("invalid covariant return type for %q+#D", overrider);
193138fd1498Szrj 	  inform (DECL_SOURCE_LOCATION (basefn),
193238fd1498Szrj 		  "overridden function is %q#D", basefn);
193338fd1498Szrj 	}
193438fd1498Szrj       else
193538fd1498Szrj 	{
193638fd1498Szrj 	  error ("conflicting return type specified for %q+#D", overrider);
193738fd1498Szrj 	  inform (DECL_SOURCE_LOCATION (basefn),
193838fd1498Szrj 		  "overridden function is %q#D", basefn);
193938fd1498Szrj 	}
194038fd1498Szrj       DECL_INVALID_OVERRIDER_P (overrider) = 1;
194138fd1498Szrj       return 0;
194238fd1498Szrj     }
194338fd1498Szrj 
194438fd1498Szrj   /* Check throw specifier is at least as strict.  */
194538fd1498Szrj   maybe_instantiate_noexcept (basefn);
194638fd1498Szrj   maybe_instantiate_noexcept (overrider);
194738fd1498Szrj   base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
194838fd1498Szrj   over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
194938fd1498Szrj 
195038fd1498Szrj   if (!comp_except_specs (base_throw, over_throw, ce_derived))
195138fd1498Szrj     {
195238fd1498Szrj       error ("looser throw specifier for %q+#F", overrider);
195338fd1498Szrj       inform (DECL_SOURCE_LOCATION (basefn),
195438fd1498Szrj 	      "overridden function is %q#F", basefn);
195538fd1498Szrj       DECL_INVALID_OVERRIDER_P (overrider) = 1;
195638fd1498Szrj       return 0;
195738fd1498Szrj     }
195838fd1498Szrj 
195938fd1498Szrj   /* Check for conflicting type attributes.  But leave transaction_safe for
196038fd1498Szrj      set_one_vmethod_tm_attributes.  */
196138fd1498Szrj   if (!comp_type_attributes (over_type, base_type)
196238fd1498Szrj       && !tx_safe_fn_type_p (base_type)
196338fd1498Szrj       && !tx_safe_fn_type_p (over_type))
196438fd1498Szrj     {
196538fd1498Szrj       error ("conflicting type attributes specified for %q+#D", overrider);
196638fd1498Szrj       inform (DECL_SOURCE_LOCATION (basefn),
196738fd1498Szrj 	      "overridden function is %q#D", basefn);
196838fd1498Szrj       DECL_INVALID_OVERRIDER_P (overrider) = 1;
196938fd1498Szrj       return 0;
197038fd1498Szrj     }
197138fd1498Szrj 
197238fd1498Szrj   /* A function declared transaction_safe_dynamic that overrides a function
197338fd1498Szrj      declared transaction_safe (but not transaction_safe_dynamic) is
197438fd1498Szrj      ill-formed.  */
197538fd1498Szrj   if (tx_safe_fn_type_p (base_type)
197638fd1498Szrj       && lookup_attribute ("transaction_safe_dynamic",
197738fd1498Szrj 			   DECL_ATTRIBUTES (overrider))
197838fd1498Szrj       && !lookup_attribute ("transaction_safe_dynamic",
197938fd1498Szrj 			    DECL_ATTRIBUTES (basefn)))
198038fd1498Szrj     {
198138fd1498Szrj       error_at (DECL_SOURCE_LOCATION (overrider),
198238fd1498Szrj 		"%qD declared %<transaction_safe_dynamic%>", overrider);
198338fd1498Szrj       inform (DECL_SOURCE_LOCATION (basefn),
198438fd1498Szrj 	      "overriding %qD declared %<transaction_safe%>", basefn);
198538fd1498Szrj     }
198638fd1498Szrj 
198738fd1498Szrj   if (DECL_DELETED_FN (basefn) != DECL_DELETED_FN (overrider))
198838fd1498Szrj     {
198938fd1498Szrj       if (DECL_DELETED_FN (overrider))
199038fd1498Szrj 	{
199138fd1498Szrj 	  error ("deleted function %q+D overriding non-deleted function",
199238fd1498Szrj 		 overrider);
199338fd1498Szrj 	  inform (DECL_SOURCE_LOCATION (basefn),
199438fd1498Szrj 		  "overridden function is %qD", basefn);
199538fd1498Szrj 	  maybe_explain_implicit_delete (overrider);
199638fd1498Szrj 	}
199738fd1498Szrj       else
199838fd1498Szrj 	{
199938fd1498Szrj 	  error ("non-deleted function %q+D overriding deleted function",
200038fd1498Szrj 		 overrider);
200138fd1498Szrj 	  inform (DECL_SOURCE_LOCATION (basefn),
200238fd1498Szrj 		  "overridden function is %qD", basefn);
200338fd1498Szrj 	}
200438fd1498Szrj       return 0;
200538fd1498Szrj     }
200638fd1498Szrj   if (DECL_FINAL_P (basefn))
200738fd1498Szrj     {
200838fd1498Szrj       error ("virtual function %q+D overriding final function", overrider);
200938fd1498Szrj       inform (DECL_SOURCE_LOCATION (basefn),
201038fd1498Szrj 	      "overridden function is %qD", basefn);
201138fd1498Szrj       return 0;
201238fd1498Szrj     }
201338fd1498Szrj   return 1;
201438fd1498Szrj }
201538fd1498Szrj 
201638fd1498Szrj /* Given a class TYPE, and a function decl FNDECL, look for
201738fd1498Szrj    virtual functions in TYPE's hierarchy which FNDECL overrides.
201838fd1498Szrj    We do not look in TYPE itself, only its bases.
201938fd1498Szrj 
202038fd1498Szrj    Returns nonzero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
202138fd1498Szrj    find that it overrides anything.
202238fd1498Szrj 
202338fd1498Szrj    We check that every function which is overridden, is correctly
202438fd1498Szrj    overridden.  */
202538fd1498Szrj 
202638fd1498Szrj int
look_for_overrides(tree type,tree fndecl)202738fd1498Szrj look_for_overrides (tree type, tree fndecl)
202838fd1498Szrj {
202938fd1498Szrj   tree binfo = TYPE_BINFO (type);
203038fd1498Szrj   tree base_binfo;
203138fd1498Szrj   int ix;
203238fd1498Szrj   int found = 0;
203338fd1498Szrj 
203438fd1498Szrj   /* A constructor for a class T does not override a function T
203538fd1498Szrj      in a base class.  */
203638fd1498Szrj   if (DECL_CONSTRUCTOR_P (fndecl))
203738fd1498Szrj     return 0;
203838fd1498Szrj 
203938fd1498Szrj   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
204038fd1498Szrj     {
204138fd1498Szrj       tree basetype = BINFO_TYPE (base_binfo);
204238fd1498Szrj 
204338fd1498Szrj       if (TYPE_POLYMORPHIC_P (basetype))
204438fd1498Szrj 	found += look_for_overrides_r (basetype, fndecl);
204538fd1498Szrj     }
204638fd1498Szrj   return found;
204738fd1498Szrj }
204838fd1498Szrj 
204938fd1498Szrj /* Look in TYPE for virtual functions with the same signature as
205038fd1498Szrj    FNDECL.  */
205138fd1498Szrj 
205238fd1498Szrj tree
look_for_overrides_here(tree type,tree fndecl)205338fd1498Szrj look_for_overrides_here (tree type, tree fndecl)
205438fd1498Szrj {
205538fd1498Szrj   tree ovl = get_class_binding (type, DECL_NAME (fndecl));
205638fd1498Szrj 
205738fd1498Szrj   for (ovl_iterator iter (ovl); iter; ++iter)
205838fd1498Szrj     {
205938fd1498Szrj       tree fn = *iter;
206038fd1498Szrj 
206138fd1498Szrj       if (!DECL_VIRTUAL_P (fn))
206238fd1498Szrj 	/* Not a virtual.  */;
206338fd1498Szrj       else if (DECL_CONTEXT (fn) != type)
206438fd1498Szrj 	/* Introduced with a using declaration.  */;
206538fd1498Szrj       else if (DECL_STATIC_FUNCTION_P (fndecl))
206638fd1498Szrj 	{
206738fd1498Szrj 	  tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
206838fd1498Szrj 	  tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
206938fd1498Szrj 	  if (compparms (TREE_CHAIN (btypes), dtypes))
207038fd1498Szrj 	    return fn;
207138fd1498Szrj 	}
207238fd1498Szrj       else if (same_signature_p (fndecl, fn))
207338fd1498Szrj 	return fn;
207438fd1498Szrj     }
207538fd1498Szrj 
207638fd1498Szrj   return NULL_TREE;
207738fd1498Szrj }
207838fd1498Szrj 
207938fd1498Szrj /* Look in TYPE for virtual functions overridden by FNDECL. Check both
208038fd1498Szrj    TYPE itself and its bases.  */
208138fd1498Szrj 
208238fd1498Szrj static int
look_for_overrides_r(tree type,tree fndecl)208338fd1498Szrj look_for_overrides_r (tree type, tree fndecl)
208438fd1498Szrj {
208538fd1498Szrj   tree fn = look_for_overrides_here (type, fndecl);
208638fd1498Szrj   if (fn)
208738fd1498Szrj     {
208838fd1498Szrj       if (DECL_STATIC_FUNCTION_P (fndecl))
208938fd1498Szrj 	{
209038fd1498Szrj 	  /* A static member function cannot match an inherited
209138fd1498Szrj 	     virtual member function.  */
209238fd1498Szrj 	  error ("%q+#D cannot be declared", fndecl);
209338fd1498Szrj 	  error ("  since %q+#D declared in base class", fn);
209438fd1498Szrj 	}
209538fd1498Szrj       else
209638fd1498Szrj 	{
209738fd1498Szrj 	  /* It's definitely virtual, even if not explicitly set.  */
209838fd1498Szrj 	  DECL_VIRTUAL_P (fndecl) = 1;
209938fd1498Szrj 	  check_final_overrider (fndecl, fn);
210038fd1498Szrj 	}
210138fd1498Szrj       return 1;
210238fd1498Szrj     }
210338fd1498Szrj 
210438fd1498Szrj   /* We failed to find one declared in this class. Look in its bases.  */
210538fd1498Szrj   return look_for_overrides (type, fndecl);
210638fd1498Szrj }
210738fd1498Szrj 
210838fd1498Szrj /* Called via dfs_walk from dfs_get_pure_virtuals.  */
210938fd1498Szrj 
211038fd1498Szrj static tree
dfs_get_pure_virtuals(tree binfo,void * data)211138fd1498Szrj dfs_get_pure_virtuals (tree binfo, void *data)
211238fd1498Szrj {
211338fd1498Szrj   tree type = (tree) data;
211438fd1498Szrj 
211538fd1498Szrj   /* We're not interested in primary base classes; the derived class
211638fd1498Szrj      of which they are a primary base will contain the information we
211738fd1498Szrj      need.  */
211838fd1498Szrj   if (!BINFO_PRIMARY_P (binfo))
211938fd1498Szrj     {
212038fd1498Szrj       tree virtuals;
212138fd1498Szrj 
212238fd1498Szrj       for (virtuals = BINFO_VIRTUALS (binfo);
212338fd1498Szrj 	   virtuals;
212438fd1498Szrj 	   virtuals = TREE_CHAIN (virtuals))
212538fd1498Szrj 	if (DECL_PURE_VIRTUAL_P (BV_FN (virtuals)))
212638fd1498Szrj 	  vec_safe_push (CLASSTYPE_PURE_VIRTUALS (type), BV_FN (virtuals));
212738fd1498Szrj     }
212838fd1498Szrj 
212938fd1498Szrj   return NULL_TREE;
213038fd1498Szrj }
213138fd1498Szrj 
213238fd1498Szrj /* Set CLASSTYPE_PURE_VIRTUALS for TYPE.  */
213338fd1498Szrj 
213438fd1498Szrj void
get_pure_virtuals(tree type)213538fd1498Szrj get_pure_virtuals (tree type)
213638fd1498Szrj {
213738fd1498Szrj   /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
213838fd1498Szrj      is going to be overridden.  */
213938fd1498Szrj   CLASSTYPE_PURE_VIRTUALS (type) = NULL;
214038fd1498Szrj   /* Now, run through all the bases which are not primary bases, and
214138fd1498Szrj      collect the pure virtual functions.  We look at the vtable in
214238fd1498Szrj      each class to determine what pure virtual functions are present.
214338fd1498Szrj      (A primary base is not interesting because the derived class of
214438fd1498Szrj      which it is a primary base will contain vtable entries for the
214538fd1498Szrj      pure virtuals in the base class.  */
214638fd1498Szrj   dfs_walk_once (TYPE_BINFO (type), NULL, dfs_get_pure_virtuals, type);
214738fd1498Szrj }
214838fd1498Szrj 
214938fd1498Szrj /* Debug info for C++ classes can get very large; try to avoid
215038fd1498Szrj    emitting it everywhere.
215138fd1498Szrj 
215238fd1498Szrj    Note that this optimization wins even when the target supports
215338fd1498Szrj    BINCL (if only slightly), and reduces the amount of work for the
215438fd1498Szrj    linker.  */
215538fd1498Szrj 
215638fd1498Szrj void
maybe_suppress_debug_info(tree t)215738fd1498Szrj maybe_suppress_debug_info (tree t)
215838fd1498Szrj {
215938fd1498Szrj   if (write_symbols == NO_DEBUG)
216038fd1498Szrj     return;
216138fd1498Szrj 
216238fd1498Szrj   /* We might have set this earlier in cp_finish_decl.  */
216338fd1498Szrj   TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 0;
216438fd1498Szrj 
216538fd1498Szrj   /* Always emit the information for each class every time. */
216638fd1498Szrj   if (flag_emit_class_debug_always)
216738fd1498Szrj     return;
216838fd1498Szrj 
216938fd1498Szrj   /* If we already know how we're handling this class, handle debug info
217038fd1498Szrj      the same way.  */
217138fd1498Szrj   if (CLASSTYPE_INTERFACE_KNOWN (t))
217238fd1498Szrj     {
217338fd1498Szrj       if (CLASSTYPE_INTERFACE_ONLY (t))
217438fd1498Szrj 	TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
217538fd1498Szrj       /* else don't set it.  */
217638fd1498Szrj     }
217738fd1498Szrj   /* If the class has a vtable, write out the debug info along with
217838fd1498Szrj      the vtable.  */
217938fd1498Szrj   else if (TYPE_CONTAINS_VPTR_P (t))
218038fd1498Szrj     TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
218138fd1498Szrj 
218238fd1498Szrj   /* Otherwise, just emit the debug info normally.  */
218338fd1498Szrj }
218438fd1498Szrj 
218538fd1498Szrj /* Note that we want debugging information for a base class of a class
218638fd1498Szrj    whose vtable is being emitted.  Normally, this would happen because
218738fd1498Szrj    calling the constructor for a derived class implies calling the
218838fd1498Szrj    constructors for all bases, which involve initializing the
218938fd1498Szrj    appropriate vptr with the vtable for the base class; but in the
219038fd1498Szrj    presence of optimization, this initialization may be optimized
219138fd1498Szrj    away, so we tell finish_vtable_vardecl that we want the debugging
219238fd1498Szrj    information anyway.  */
219338fd1498Szrj 
219438fd1498Szrj static tree
dfs_debug_mark(tree binfo,void *)219538fd1498Szrj dfs_debug_mark (tree binfo, void * /*data*/)
219638fd1498Szrj {
219738fd1498Szrj   tree t = BINFO_TYPE (binfo);
219838fd1498Szrj 
219938fd1498Szrj   if (CLASSTYPE_DEBUG_REQUESTED (t))
220038fd1498Szrj     return dfs_skip_bases;
220138fd1498Szrj 
220238fd1498Szrj   CLASSTYPE_DEBUG_REQUESTED (t) = 1;
220338fd1498Szrj 
220438fd1498Szrj   return NULL_TREE;
220538fd1498Szrj }
220638fd1498Szrj 
220738fd1498Szrj /* Write out the debugging information for TYPE, whose vtable is being
220838fd1498Szrj    emitted.  Also walk through our bases and note that we want to
220938fd1498Szrj    write out information for them.  This avoids the problem of not
221038fd1498Szrj    writing any debug info for intermediate basetypes whose
221138fd1498Szrj    constructors, and thus the references to their vtables, and thus
221238fd1498Szrj    the vtables themselves, were optimized away.  */
221338fd1498Szrj 
221438fd1498Szrj void
note_debug_info_needed(tree type)221538fd1498Szrj note_debug_info_needed (tree type)
221638fd1498Szrj {
221738fd1498Szrj   if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
221838fd1498Szrj     {
221938fd1498Szrj       TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)) = 0;
222038fd1498Szrj       rest_of_type_compilation (type, namespace_bindings_p ());
222138fd1498Szrj     }
222238fd1498Szrj 
222338fd1498Szrj   dfs_walk_all (TYPE_BINFO (type), dfs_debug_mark, NULL, 0);
222438fd1498Szrj }
222538fd1498Szrj 
222638fd1498Szrj /* Helper for lookup_conversions_r.  TO_TYPE is the type converted to
222738fd1498Szrj    by a conversion op in base BINFO.  VIRTUAL_DEPTH is nonzero if
222838fd1498Szrj    BINFO is morally virtual, and VIRTUALNESS is nonzero if virtual
222938fd1498Szrj    bases have been encountered already in the tree walk.  PARENT_CONVS
223038fd1498Szrj    is the list of lists of conversion functions that could hide CONV
223138fd1498Szrj    and OTHER_CONVS is the list of lists of conversion functions that
223238fd1498Szrj    could hide or be hidden by CONV, should virtualness be involved in
223338fd1498Szrj    the hierarchy.  Merely checking the conversion op's name is not
223438fd1498Szrj    enough because two conversion operators to the same type can have
223538fd1498Szrj    different names.  Return nonzero if we are visible.  */
223638fd1498Szrj 
223738fd1498Szrj static int
check_hidden_convs(tree binfo,int virtual_depth,int virtualness,tree to_type,tree parent_convs,tree other_convs)223838fd1498Szrj check_hidden_convs (tree binfo, int virtual_depth, int virtualness,
223938fd1498Szrj 		    tree to_type, tree parent_convs, tree other_convs)
224038fd1498Szrj {
224138fd1498Szrj   tree level, probe;
224238fd1498Szrj 
224338fd1498Szrj   /* See if we are hidden by a parent conversion.  */
224438fd1498Szrj   for (level = parent_convs; level; level = TREE_CHAIN (level))
224538fd1498Szrj     for (probe = TREE_VALUE (level); probe; probe = TREE_CHAIN (probe))
224638fd1498Szrj       if (same_type_p (to_type, TREE_TYPE (probe)))
224738fd1498Szrj 	return 0;
224838fd1498Szrj 
224938fd1498Szrj   if (virtual_depth || virtualness)
225038fd1498Szrj     {
225138fd1498Szrj      /* In a virtual hierarchy, we could be hidden, or could hide a
225238fd1498Szrj 	conversion function on the other_convs list.  */
225338fd1498Szrj       for (level = other_convs; level; level = TREE_CHAIN (level))
225438fd1498Szrj 	{
225538fd1498Szrj 	  int we_hide_them;
225638fd1498Szrj 	  int they_hide_us;
225738fd1498Szrj 	  tree *prev, other;
225838fd1498Szrj 
225938fd1498Szrj 	  if (!(virtual_depth || TREE_STATIC (level)))
226038fd1498Szrj 	    /* Neither is morally virtual, so cannot hide each other.  */
226138fd1498Szrj 	    continue;
226238fd1498Szrj 
226338fd1498Szrj 	  if (!TREE_VALUE (level))
226438fd1498Szrj 	    /* They evaporated away already.  */
226538fd1498Szrj 	    continue;
226638fd1498Szrj 
226738fd1498Szrj 	  they_hide_us = (virtual_depth
226838fd1498Szrj 			  && original_binfo (binfo, TREE_PURPOSE (level)));
226938fd1498Szrj 	  we_hide_them = (!they_hide_us && TREE_STATIC (level)
227038fd1498Szrj 			  && original_binfo (TREE_PURPOSE (level), binfo));
227138fd1498Szrj 
227238fd1498Szrj 	  if (!(we_hide_them || they_hide_us))
227338fd1498Szrj 	    /* Neither is within the other, so no hiding can occur.  */
227438fd1498Szrj 	    continue;
227538fd1498Szrj 
227638fd1498Szrj 	  for (prev = &TREE_VALUE (level), other = *prev; other;)
227738fd1498Szrj 	    {
227838fd1498Szrj 	      if (same_type_p (to_type, TREE_TYPE (other)))
227938fd1498Szrj 		{
228038fd1498Szrj 		  if (they_hide_us)
228138fd1498Szrj 		    /* We are hidden.  */
228238fd1498Szrj 		    return 0;
228338fd1498Szrj 
228438fd1498Szrj 		  if (we_hide_them)
228538fd1498Szrj 		    {
228638fd1498Szrj 		      /* We hide the other one.  */
228738fd1498Szrj 		      other = TREE_CHAIN (other);
228838fd1498Szrj 		      *prev = other;
228938fd1498Szrj 		      continue;
229038fd1498Szrj 		    }
229138fd1498Szrj 		}
229238fd1498Szrj 	      prev = &TREE_CHAIN (other);
229338fd1498Szrj 	      other = *prev;
229438fd1498Szrj 	    }
229538fd1498Szrj 	}
229638fd1498Szrj     }
229738fd1498Szrj   return 1;
229838fd1498Szrj }
229938fd1498Szrj 
230038fd1498Szrj /* Helper for lookup_conversions_r.  PARENT_CONVS is a list of lists
230138fd1498Szrj    of conversion functions, the first slot will be for the current
230238fd1498Szrj    binfo, if MY_CONVS is non-NULL.  CHILD_CONVS is the list of lists
230338fd1498Szrj    of conversion functions from children of the current binfo,
230438fd1498Szrj    concatenated with conversions from elsewhere in the hierarchy --
230538fd1498Szrj    that list begins with OTHER_CONVS.  Return a single list of lists
230638fd1498Szrj    containing only conversions from the current binfo and its
230738fd1498Szrj    children.  */
230838fd1498Szrj 
230938fd1498Szrj static tree
split_conversions(tree my_convs,tree parent_convs,tree child_convs,tree other_convs)231038fd1498Szrj split_conversions (tree my_convs, tree parent_convs,
231138fd1498Szrj 		   tree child_convs, tree other_convs)
231238fd1498Szrj {
231338fd1498Szrj   tree t;
231438fd1498Szrj   tree prev;
231538fd1498Szrj 
231638fd1498Szrj   /* Remove the original other_convs portion from child_convs.  */
231738fd1498Szrj   for (prev = NULL, t = child_convs;
231838fd1498Szrj        t != other_convs; prev = t, t = TREE_CHAIN (t))
231938fd1498Szrj     continue;
232038fd1498Szrj 
232138fd1498Szrj   if (prev)
232238fd1498Szrj     TREE_CHAIN (prev) = NULL_TREE;
232338fd1498Szrj   else
232438fd1498Szrj     child_convs = NULL_TREE;
232538fd1498Szrj 
232638fd1498Szrj   /* Attach the child convs to any we had at this level.  */
232738fd1498Szrj   if (my_convs)
232838fd1498Szrj     {
232938fd1498Szrj       my_convs = parent_convs;
233038fd1498Szrj       TREE_CHAIN (my_convs) = child_convs;
233138fd1498Szrj     }
233238fd1498Szrj   else
233338fd1498Szrj     my_convs = child_convs;
233438fd1498Szrj 
233538fd1498Szrj   return my_convs;
233638fd1498Szrj }
233738fd1498Szrj 
233838fd1498Szrj /* Worker for lookup_conversions.  Lookup conversion functions in
233938fd1498Szrj    BINFO and its children.  VIRTUAL_DEPTH is nonzero, if BINFO is in a
234038fd1498Szrj    morally virtual base, and VIRTUALNESS is nonzero, if we've
234138fd1498Szrj    encountered virtual bases already in the tree walk.  PARENT_CONVS
234238fd1498Szrj    is a list of conversions within parent binfos.  OTHER_CONVS are
234338fd1498Szrj    conversions found elsewhere in the tree.  Return the conversions
234438fd1498Szrj    found within this portion of the graph in CONVS.  Return nonzero if
234538fd1498Szrj    we encountered virtualness.  We keep template and non-template
234638fd1498Szrj    conversions separate, to avoid unnecessary type comparisons.
234738fd1498Szrj 
234838fd1498Szrj    The located conversion functions are held in lists of lists.  The
234938fd1498Szrj    TREE_VALUE of the outer list is the list of conversion functions
235038fd1498Szrj    found in a particular binfo.  The TREE_PURPOSE of both the outer
235138fd1498Szrj    and inner lists is the binfo at which those conversions were
235238fd1498Szrj    found.  TREE_STATIC is set for those lists within of morally
235338fd1498Szrj    virtual binfos.  The TREE_VALUE of the inner list is the conversion
235438fd1498Szrj    function or overload itself.  The TREE_TYPE of each inner list node
235538fd1498Szrj    is the converted-to type.  */
235638fd1498Szrj 
235738fd1498Szrj static int
lookup_conversions_r(tree binfo,int virtual_depth,int virtualness,tree parent_convs,tree other_convs,tree * convs)235838fd1498Szrj lookup_conversions_r (tree binfo, int virtual_depth, int virtualness,
235938fd1498Szrj 		      tree parent_convs, tree other_convs, tree *convs)
236038fd1498Szrj {
236138fd1498Szrj   int my_virtualness = 0;
236238fd1498Szrj   tree my_convs = NULL_TREE;
236338fd1498Szrj   tree child_convs = NULL_TREE;
236438fd1498Szrj 
236538fd1498Szrj   /* If we have no conversion operators, then don't look.  */
236638fd1498Szrj   if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo)))
236738fd1498Szrj     {
236838fd1498Szrj       *convs = NULL_TREE;
236938fd1498Szrj 
237038fd1498Szrj       return 0;
237138fd1498Szrj     }
237238fd1498Szrj 
237338fd1498Szrj   if (BINFO_VIRTUAL_P (binfo))
237438fd1498Szrj     virtual_depth++;
237538fd1498Szrj 
237638fd1498Szrj   /* First, locate the unhidden ones at this level.  */
237738fd1498Szrj   if (tree conv = get_class_binding (BINFO_TYPE (binfo), conv_op_identifier))
237838fd1498Szrj   for (ovl_iterator iter (conv); iter; ++iter)
237938fd1498Szrj     {
238038fd1498Szrj       tree fn = *iter;
238138fd1498Szrj       tree type = DECL_CONV_FN_TYPE (fn);
238238fd1498Szrj 
238338fd1498Szrj       if (TREE_CODE (fn) != TEMPLATE_DECL && type_uses_auto (type))
238438fd1498Szrj 	{
238538fd1498Szrj 	  mark_used (fn);
238638fd1498Szrj 	  type = DECL_CONV_FN_TYPE (fn);
238738fd1498Szrj 	}
238838fd1498Szrj 
238938fd1498Szrj       if (check_hidden_convs (binfo, virtual_depth, virtualness,
239038fd1498Szrj 			      type, parent_convs, other_convs))
239138fd1498Szrj 	{
239238fd1498Szrj 	  my_convs = tree_cons (binfo, fn, my_convs);
239338fd1498Szrj 	  TREE_TYPE (my_convs) = type;
239438fd1498Szrj 	  if (virtual_depth)
239538fd1498Szrj 	    {
239638fd1498Szrj 	      TREE_STATIC (my_convs) = 1;
239738fd1498Szrj 	      my_virtualness = 1;
239838fd1498Szrj 	    }
239938fd1498Szrj 	}
240038fd1498Szrj     }
240138fd1498Szrj 
240238fd1498Szrj   if (my_convs)
240338fd1498Szrj     {
240438fd1498Szrj       parent_convs = tree_cons (binfo, my_convs, parent_convs);
240538fd1498Szrj       if (virtual_depth)
240638fd1498Szrj 	TREE_STATIC (parent_convs) = 1;
240738fd1498Szrj     }
240838fd1498Szrj 
240938fd1498Szrj   child_convs = other_convs;
241038fd1498Szrj 
241138fd1498Szrj   /* Now iterate over each base, looking for more conversions.  */
241238fd1498Szrj   unsigned i;
241338fd1498Szrj   tree base_binfo;
241438fd1498Szrj   for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
241538fd1498Szrj     {
241638fd1498Szrj       tree base_convs;
241738fd1498Szrj       unsigned base_virtualness;
241838fd1498Szrj 
241938fd1498Szrj       base_virtualness = lookup_conversions_r (base_binfo,
242038fd1498Szrj 					       virtual_depth, virtualness,
242138fd1498Szrj 					       parent_convs, child_convs,
242238fd1498Szrj 					       &base_convs);
242338fd1498Szrj       if (base_virtualness)
242438fd1498Szrj 	my_virtualness = virtualness = 1;
242538fd1498Szrj       child_convs = chainon (base_convs, child_convs);
242638fd1498Szrj     }
242738fd1498Szrj 
242838fd1498Szrj   *convs = split_conversions (my_convs, parent_convs,
242938fd1498Szrj 			      child_convs, other_convs);
243038fd1498Szrj 
243138fd1498Szrj   return my_virtualness;
243238fd1498Szrj }
243338fd1498Szrj 
243438fd1498Szrj /* Return a TREE_LIST containing all the non-hidden user-defined
243538fd1498Szrj    conversion functions for TYPE (and its base-classes).  The
243638fd1498Szrj    TREE_VALUE of each node is the FUNCTION_DECL of the conversion
243738fd1498Szrj    function.  The TREE_PURPOSE is the BINFO from which the conversion
243838fd1498Szrj    functions in this node were selected.  This function is effectively
243938fd1498Szrj    performing a set of member lookups as lookup_fnfield does, but
244038fd1498Szrj    using the type being converted to as the unique key, rather than the
244138fd1498Szrj    field name.  */
244238fd1498Szrj 
244338fd1498Szrj tree
lookup_conversions(tree type)244438fd1498Szrj lookup_conversions (tree type)
244538fd1498Szrj {
244638fd1498Szrj   tree convs;
244738fd1498Szrj 
244838fd1498Szrj   complete_type (type);
244938fd1498Szrj   if (!CLASS_TYPE_P (type) || !TYPE_BINFO (type))
245038fd1498Szrj     return NULL_TREE;
245138fd1498Szrj 
245238fd1498Szrj   lookup_conversions_r (TYPE_BINFO (type), 0, 0, NULL_TREE, NULL_TREE, &convs);
245338fd1498Szrj 
245438fd1498Szrj   tree list = NULL_TREE;
245538fd1498Szrj 
245638fd1498Szrj   /* Flatten the list-of-lists */
245738fd1498Szrj   for (; convs; convs = TREE_CHAIN (convs))
245838fd1498Szrj     {
245938fd1498Szrj       tree probe, next;
246038fd1498Szrj 
246138fd1498Szrj       for (probe = TREE_VALUE (convs); probe; probe = next)
246238fd1498Szrj 	{
246338fd1498Szrj 	  next = TREE_CHAIN (probe);
246438fd1498Szrj 
246538fd1498Szrj 	  TREE_CHAIN (probe) = list;
246638fd1498Szrj 	  list = probe;
246738fd1498Szrj 	}
246838fd1498Szrj     }
246938fd1498Szrj 
247038fd1498Szrj   return list;
247138fd1498Szrj }
247238fd1498Szrj 
247338fd1498Szrj /* Returns the binfo of the first direct or indirect virtual base derived
247438fd1498Szrj    from BINFO, or NULL if binfo is not via virtual.  */
247538fd1498Szrj 
247638fd1498Szrj tree
binfo_from_vbase(tree binfo)247738fd1498Szrj binfo_from_vbase (tree binfo)
247838fd1498Szrj {
247938fd1498Szrj   for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
248038fd1498Szrj     {
248138fd1498Szrj       if (BINFO_VIRTUAL_P (binfo))
248238fd1498Szrj 	return binfo;
248338fd1498Szrj     }
248438fd1498Szrj   return NULL_TREE;
248538fd1498Szrj }
248638fd1498Szrj 
248738fd1498Szrj /* Returns the binfo of the first direct or indirect virtual base derived
248838fd1498Szrj    from BINFO up to the TREE_TYPE, LIMIT, or NULL if binfo is not
248938fd1498Szrj    via virtual.  */
249038fd1498Szrj 
249138fd1498Szrj tree
binfo_via_virtual(tree binfo,tree limit)249238fd1498Szrj binfo_via_virtual (tree binfo, tree limit)
249338fd1498Szrj {
249438fd1498Szrj   if (limit && !CLASSTYPE_VBASECLASSES (limit))
249538fd1498Szrj     /* LIMIT has no virtual bases, so BINFO cannot be via one.  */
249638fd1498Szrj     return NULL_TREE;
249738fd1498Szrj 
249838fd1498Szrj   for (; binfo && !SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), limit);
249938fd1498Szrj        binfo = BINFO_INHERITANCE_CHAIN (binfo))
250038fd1498Szrj     {
250138fd1498Szrj       if (BINFO_VIRTUAL_P (binfo))
250238fd1498Szrj 	return binfo;
250338fd1498Szrj     }
250438fd1498Szrj   return NULL_TREE;
250538fd1498Szrj }
250638fd1498Szrj 
250738fd1498Szrj /* BINFO is for a base class in some hierarchy.  Return true iff it is a
250838fd1498Szrj    direct base.  */
250938fd1498Szrj 
251038fd1498Szrj bool
binfo_direct_p(tree binfo)251138fd1498Szrj binfo_direct_p (tree binfo)
251238fd1498Szrj {
251338fd1498Szrj   tree d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
251438fd1498Szrj   if (BINFO_INHERITANCE_CHAIN (d_binfo))
251538fd1498Szrj     /* A second inheritance chain means indirect.  */
251638fd1498Szrj     return false;
251738fd1498Szrj   if (!BINFO_VIRTUAL_P (binfo))
251838fd1498Szrj     /* Non-virtual, so only one inheritance chain means direct.  */
251938fd1498Szrj     return true;
252038fd1498Szrj   /* A virtual base looks like a direct base, so we need to look through the
252138fd1498Szrj      direct bases to see if it's there.  */
252238fd1498Szrj   tree b_binfo;
252338fd1498Szrj   for (int i = 0; BINFO_BASE_ITERATE (d_binfo, i, b_binfo); ++i)
252438fd1498Szrj     if (b_binfo == binfo)
252538fd1498Szrj       return true;
252638fd1498Szrj   return false;
252738fd1498Szrj }
252838fd1498Szrj 
252938fd1498Szrj /* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
253038fd1498Szrj    Find the equivalent binfo within whatever graph HERE is located.
253138fd1498Szrj    This is the inverse of original_binfo.  */
253238fd1498Szrj 
253338fd1498Szrj tree
copied_binfo(tree binfo,tree here)253438fd1498Szrj copied_binfo (tree binfo, tree here)
253538fd1498Szrj {
253638fd1498Szrj   tree result = NULL_TREE;
253738fd1498Szrj 
253838fd1498Szrj   if (BINFO_VIRTUAL_P (binfo))
253938fd1498Szrj     {
254038fd1498Szrj       tree t;
254138fd1498Szrj 
254238fd1498Szrj       for (t = here; BINFO_INHERITANCE_CHAIN (t);
254338fd1498Szrj 	   t = BINFO_INHERITANCE_CHAIN (t))
254438fd1498Szrj 	continue;
254538fd1498Szrj 
254638fd1498Szrj       result = binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (t));
254738fd1498Szrj     }
254838fd1498Szrj   else if (BINFO_INHERITANCE_CHAIN (binfo))
254938fd1498Szrj     {
255038fd1498Szrj       tree cbinfo;
255138fd1498Szrj       tree base_binfo;
255238fd1498Szrj       int ix;
255338fd1498Szrj 
255438fd1498Szrj       cbinfo = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
255538fd1498Szrj       for (ix = 0; BINFO_BASE_ITERATE (cbinfo, ix, base_binfo); ix++)
255638fd1498Szrj 	if (SAME_BINFO_TYPE_P (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)))
255738fd1498Szrj 	  {
255838fd1498Szrj 	    result = base_binfo;
255938fd1498Szrj 	    break;
256038fd1498Szrj 	  }
256138fd1498Szrj     }
256238fd1498Szrj   else
256338fd1498Szrj     {
256438fd1498Szrj       gcc_assert (SAME_BINFO_TYPE_P (BINFO_TYPE (here), BINFO_TYPE (binfo)));
256538fd1498Szrj       result = here;
256638fd1498Szrj     }
256738fd1498Szrj 
256838fd1498Szrj   gcc_assert (result);
256938fd1498Szrj   return result;
257038fd1498Szrj }
257138fd1498Szrj 
257238fd1498Szrj tree
binfo_for_vbase(tree base,tree t)257338fd1498Szrj binfo_for_vbase (tree base, tree t)
257438fd1498Szrj {
257538fd1498Szrj   unsigned ix;
257638fd1498Szrj   tree binfo;
257738fd1498Szrj   vec<tree, va_gc> *vbases;
257838fd1498Szrj 
257938fd1498Szrj   for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
258038fd1498Szrj        vec_safe_iterate (vbases, ix, &binfo); ix++)
258138fd1498Szrj     if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), base))
258238fd1498Szrj       return binfo;
258338fd1498Szrj   return NULL;
258438fd1498Szrj }
258538fd1498Szrj 
258638fd1498Szrj /* BINFO is some base binfo of HERE, within some other
258738fd1498Szrj    hierarchy. Return the equivalent binfo, but in the hierarchy
258838fd1498Szrj    dominated by HERE.  This is the inverse of copied_binfo.  If BINFO
258938fd1498Szrj    is not a base binfo of HERE, returns NULL_TREE.  */
259038fd1498Szrj 
259138fd1498Szrj tree
original_binfo(tree binfo,tree here)259238fd1498Szrj original_binfo (tree binfo, tree here)
259338fd1498Szrj {
259438fd1498Szrj   tree result = NULL;
259538fd1498Szrj 
259638fd1498Szrj   if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), BINFO_TYPE (here)))
259738fd1498Szrj     result = here;
259838fd1498Szrj   else if (BINFO_VIRTUAL_P (binfo))
259938fd1498Szrj     result = (CLASSTYPE_VBASECLASSES (BINFO_TYPE (here))
260038fd1498Szrj 	      ? binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (here))
260138fd1498Szrj 	      : NULL_TREE);
260238fd1498Szrj   else if (BINFO_INHERITANCE_CHAIN (binfo))
260338fd1498Szrj     {
260438fd1498Szrj       tree base_binfos;
260538fd1498Szrj 
260638fd1498Szrj       base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
260738fd1498Szrj       if (base_binfos)
260838fd1498Szrj 	{
260938fd1498Szrj 	  int ix;
261038fd1498Szrj 	  tree base_binfo;
261138fd1498Szrj 
261238fd1498Szrj 	  for (ix = 0; (base_binfo = BINFO_BASE_BINFO (base_binfos, ix)); ix++)
261338fd1498Szrj 	    if (SAME_BINFO_TYPE_P (BINFO_TYPE (base_binfo),
261438fd1498Szrj 				   BINFO_TYPE (binfo)))
261538fd1498Szrj 	      {
261638fd1498Szrj 		result = base_binfo;
261738fd1498Szrj 		break;
261838fd1498Szrj 	      }
261938fd1498Szrj 	}
262038fd1498Szrj     }
262138fd1498Szrj 
262238fd1498Szrj   return result;
262338fd1498Szrj }
262438fd1498Szrj 
262538fd1498Szrj /* True iff TYPE has any dependent bases (and therefore we can't say
262638fd1498Szrj    definitively that another class is not a base of an instantiation of
262738fd1498Szrj    TYPE).  */
262838fd1498Szrj 
262938fd1498Szrj bool
any_dependent_bases_p(tree type)263038fd1498Szrj any_dependent_bases_p (tree type)
263138fd1498Szrj {
263238fd1498Szrj   if (!type || !CLASS_TYPE_P (type) || !uses_template_parms (type))
263338fd1498Szrj     return false;
263438fd1498Szrj 
263538fd1498Szrj   /* If we haven't set TYPE_BINFO yet, we don't know anything about the bases.
263638fd1498Szrj      Return false because in this situation we aren't actually looking up names
263738fd1498Szrj      in the scope of the class, so it doesn't matter whether it has dependent
263838fd1498Szrj      bases.  */
263938fd1498Szrj   if (!TYPE_BINFO (type))
264038fd1498Szrj     return false;
264138fd1498Szrj 
264238fd1498Szrj   unsigned i;
264338fd1498Szrj   tree base_binfo;
264438fd1498Szrj   FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_BINFOS (TYPE_BINFO (type)), i, base_binfo)
264538fd1498Szrj     if (BINFO_DEPENDENT_BASE_P (base_binfo))
264638fd1498Szrj       return true;
264738fd1498Szrj 
264838fd1498Szrj   return false;
264938fd1498Szrj }
2650