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

来源:互联网 发布:js获取embed播放时间 编辑:程序博客网 时间:2024/06/05 03:56

5.9.2.2.   是否从友元访问

如果protected_accessible_p返回非0值,当前类的派生树包含了decl,而且type是当前类的一个基类(protected_accessible_p837行语句块保证),那么可以直接去检查其访问属性,而且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_typecurrent_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      return0;

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      return0;

871 

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

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

874        return1;

875 

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

877      percore 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        returnret;

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      returnret;

913    }

914 

915    return0;

916  }

 

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

5.9.2.3.   确定访问属性

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

class B;

class A {

private:

int i;

friend void f(B*);

};

class B : publicA { };

void f(B* p) {

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

}

这通过后序遍历type的派生树时,执行dfs_accessible_p的方法来查找。BINFO_ACCESS1000行的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 orprotected inheritance,

768      then we can't see it, unless we are afriend 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  }

 

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