GCC-3.4.6源代码学习笔记(85)

5.9.2.2.    是否从友元访问

如果 protected_accessible_p 返回非 0 值,当前类的派生树包含了 decl ,而且 type 是当前类的一个基类( protected_accessible_p 837 行语句块保证),那么可以直接去检查其访问属性,而且 protected 以上即可。否则,如果当前类的派生树不包含 decl ,或者 type 不是当前类的基类,那么需要检查当前作用域是否是可以访问 decl 的友元。函数 friend_accessible_p 的参数 scope (当前作用域)由下面的 current_scope 获得。

 

550  tree

551  current_scope (void)                                                                                  in search.c

552  {

553    if (current_function_decl == NULL_TREE)

554      return current_class_type ;

555    if (current_class_type == NULL_TREE)

556      return current_function_decl ;

557    if ((DECL_FUNCTION_MEMBER_P (current_function_decl )

558         && same_type_p (DECL_CONTEXT (current_function_decl ),

559                           current_class_type ))

560        || (DECL_FRIEND_CONTEXT (current_function_decl )

561           && same_type_p (DECL_FRIEND_CONTEXT (current_function_decl ),

562                          current_class_type )))

563      return current_function_decl ;

564 

565    return current_class_type ;

566  }

 

current_class_type current_function_decl 的设置情况如下表给出。

 

current_class_type

current_function_decl

global

NULL

NULL

function-local

NULL

SET

class-local

SET

NULL

class->function *

SET

SET

function->class **

SET

SET

* :包括类的函数友元。 ** GNU 的扩展,函数内的局部类

这时需要考虑的情况就是:接受当前域(可以是类,或者函数)作为友元的类包含了 decl ,而且 type 是其的一个基类。在函数 friend_accessible_p 中,参数 binfo 来自 type

 

855  static int

856  friend_accessible_p (tree scope, tree decl, tree binfo)                                           in search.c

857  {

858    tree befriending_classes;

859    tree t;

860 

861    if (!scope)

862      return 0;

863 

864    if (TREE_CODE (scope) == FUNCTION_DECL

865       || DECL_FUNCTION_TEMPLATE_P (scope))

866      befriending_classes = DECL_BEFRIENDING_CLASSES (scope);

867    else if (TYPE_P (scope))

868      befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope);

869    else

870      return 0;

871 

872    for (t = befriending_classes; t; t = TREE_CHAIN (t))

873      if (protected_accessible_p (decl, TREE_VALUE (t), binfo))

874        return 1;

875 

876    /* Nested classes are implicitly friends of their enclosing types, as

877      per core issue 45 (this is a change from the standard).  */

878    if (TYPE_P (scope))

879      for (t = TYPE_CONTEXT (scope); t && TYPE_P (t); t = TYPE_CONTEXT (t))

880        if (protected_accessible_p (decl, t, binfo))

881          return 1;

882 

883    if (TREE_CODE (scope) == FUNCTION_DECL

884      || DECL_FUNCTION_TEMPLATE_P (scope))

885    {

886      /* Perhaps this SCOPE is a member of a class which is a

887        friend.  */

888      if (DECL_CLASS_SCOPE_P (decl)

889         && friend_accessible_p (DECL_CONTEXT (scope), decl, binfo))

890        return 1;

891 

892      /* Or an instantiation of something which is a friend.  */

893      if (DECL_TEMPLATE_INFO (scope))

894      {

895        int ret;

896        /* Increment processing_template_decl to make sure that

897          dependent_type_p works correctly.  */

898        ++processing_template_decl;

899        ret = friend_accessible_p (DECL_TI_TEMPLATE (scope), decl, binfo);

900        --processing_template_decl;

901        return ret;

902      }

903    }

904    else if (CLASSTYPE_TEMPLATE_INFO (scope))

905    {

906      int ret;

907      /* Increment processing_template_decl to make sure that

908        dependent_type_p works correctly.  */

909      ++processing_template_decl;

910      ret = friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope), decl, binfo);

911       --processing_template_decl;

912      return ret;

913    }

914 

915    return 0;

916  }

 

上面的 befriending_classes 就是当前函数或类作为友元的类的列表。如果对于这些类, protected_accessible_p 还是返回 0 ,如果 scope 代表一个类,那么这里的做法是继续逐级检查包含 scope 的类;而如果 scope 代表一个类方法,则继续考察其所在类作为友元的情形。 893 行表示该方法是一个模板函数, DECL_TI_TEMPLATE 是代表其特化或具现的节点。而 904 行表示是一个模板类, CLASSTYPE_TI_TEMPLATE 是代表其特化或具现的节点。这是考察模板的特化类型是否是所期望的友元。

5.9.2.3.    确定访问属性

从上面看到,如果 protected_accessible_p friend_accessible_p 返回非 0 值,表明 decl type 都在同一棵派生树里。那么接下来,在 accessible_p 1000 行,调用 access_in_type 来考察 type decl 的访问属性。如果结果在 protected 级别以上,毫无疑问, type 可以访问 decl 。但是对于友元来说, private 级别也不是问题。因此,如果结果是 private ,那么还要看一下是否为友元。而且还有更复杂的情况,比如:

class B;

class A {

private :

int i;

friend void f(B*);

};

class B : public A { };

void f(B* p) {

p->i = 1; // OK: B* can be implicitly cast to A*, and f has access to i in A

}

这通过后序遍历 type 的派生树时,执行 dfs_accessible_p 的方法来查找。 BINFO_ACCESS 1000 行的 access_in_type 执行时,就被设置好了。如果它是 ak_none ,就表明该类与 decl 无关。

 

778  static tree

779  dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)                   in search.c

780  {

781    access_kind access;

782 

783    BINFO_MARKED (binfo) = 1;

784    access = BINFO_ACCESS (binfo);

785    if (access != ak_none

786        && is_friend (BINFO_TYPE (binfo), current_scope ()))

787      return binfo;

788 

789    return NULL_TREE;

790  }

 

类似的, dfs_accessible_queue_p 返回合适的 binfo 来递归地进入。它以中序遍历派生树。

 

759  static tree

760  dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)

761  {

762    tree binfo = BINFO_BASETYPE (derived, ix);

763   

764    if (BINFO_MARKED (binfo))

765      return NULL_TREE;

766 

767    /* If this class is inherited via private or protected inheritance,

768      then we can't see it, unless we are a friend of the derived class.  */

769    if (BINFO_BASEACCESS (derived, ix) != access_public_node

770        && !is_friend (BINFO_TYPE (derived), current_scope ()))

771      return NULL_TREE;

772 

773    return binfo;

774  }

 

这一次,只要找到一个合适的类,就返回。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值