コード例 #1
0
ファイル: friend.c プロジェクト: AHelper/gcc
void
add_friend (tree type, tree decl, bool complain)
{
  tree typedecl;
  tree list;
  tree name;
  tree ctx;

  if (decl == error_mark_node)
    return;

  typedecl = TYPE_MAIN_DECL (type);
  list = DECL_FRIENDLIST (typedecl);
  name = DECL_NAME (decl);
  type = TREE_TYPE (typedecl);

  while (list)
    {
      if (name == FRIEND_NAME (list))
	{
	  tree friends = FRIEND_DECLS (list);
	  for (; friends ; friends = TREE_CHAIN (friends))
	    {
	      if (decl == TREE_VALUE (friends))
		{
		  if (complain)
		    warning (OPT_Wredundant_decls,
			     "%qD is already a friend of class %qT",
			     decl, type);
		  return;
		}
	    }

	  maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);

	  TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
					 TREE_VALUE (list));
	  return;
	}
      list = TREE_CHAIN (list);
    }

  ctx = DECL_CONTEXT (decl);
  if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
    perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl,
				   tf_warning_or_error);

  maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);

  DECL_FRIENDLIST (typedecl)
    = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
		 DECL_FRIENDLIST (typedecl));
  if (!uses_template_parms (type))
    DECL_BEFRIENDING_CLASSES (decl)
      = tree_cons (NULL_TREE, type,
		   DECL_BEFRIENDING_CLASSES (decl));
}
コード例 #2
0
int
is_friend (tree type, tree supplicant)
{
    int declp;
    tree list;
    tree context;

    if (supplicant == NULL_TREE || type == NULL_TREE)
        return 0;

    declp = DECL_P (supplicant);

    if (declp)
        /* It's a function decl.  */
    {
        tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type));
        tree name = DECL_NAME (supplicant);

        for (; list ; list = TREE_CHAIN (list))
        {
            if (name == FRIEND_NAME (list))
            {
                tree friends = FRIEND_DECLS (list);
                for (; friends ; friends = TREE_CHAIN (friends))
                {
                    tree this_friend = TREE_VALUE (friends);

                    if (this_friend == NULL_TREE)
                        continue;

                    if (supplicant == this_friend)
                        return 1;

                    if (is_specialization_of_friend (supplicant, this_friend))
                        return 1;
                }
                break;
            }
        }
    }
    else
        /* It's a type.  */
    {
        if (same_type_p (supplicant, type))
            return 1;

        list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
        for (; list ; list = TREE_CHAIN (list))
        {
            tree t = TREE_VALUE (list);

            if (TREE_CODE (t) == TEMPLATE_DECL ?
                    is_specialization_of_friend (TYPE_MAIN_DECL (supplicant), t) :
                    same_type_p (supplicant, t))
                return 1;
        }
    }

    if (declp)
    {
        if (DECL_FUNCTION_MEMBER_P (supplicant))
            context = DECL_CONTEXT (supplicant);
        else
            context = NULL_TREE;
    }
    else
    {
        if (TYPE_CLASS_SCOPE_P (supplicant))
            /* Nested classes get the same access as their enclosing types, as
               per DR 45 (this is a change from the standard).  */
            context = TYPE_CONTEXT (supplicant);
        else
            /* Local classes have the same access as the enclosing function.  */
            context = decl_function_context (TYPE_MAIN_DECL (supplicant));
    }

    /* A namespace is not friend to anybody.  */
    if (context && TREE_CODE (context) == NAMESPACE_DECL)
        context = NULL_TREE;

    if (context)
        return is_friend (type, context);

    return 0;
}