GCC-3.4.6源代码学习笔记(85)
来源:互联网 发布:js获取embed播放时间 编辑:程序博客网 时间:2024/06/05 03:56
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 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_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 : 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_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 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 }
这一次,只要找到一个合适的类,就返回。
- GCC-3.4.6源代码学习笔记(85)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记 (102)
- GCC-3.4.6源代码学习笔记 (103)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记 (105)
- GCC-3.4.6源代码学习笔记 (106)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(2)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(4)
- GCC-3.4.6源代码学习笔记(5)
- GCC-3.4.6源代码学习笔记(7)
- GCC-3.4.6源代码学习笔记(8)
- 我的RIO测试脚本v2.0(传输层:UDP,标记法:token bucket )
- Android回顾与展望:从G1到冻酸奶Froyo
- 关于arcgis server 9.3.1 sp1的安装和配置使用
- 观点评论]浮躁的国内游戏界:浮躁的研发团队,浮躁的游戏投资商
- 在网站导航里增加“桌面快捷”
- GCC-3.4.6源代码学习笔记(85)
- Oracle 9i 安装过程中遇到 缺少 OCS4J.properties 的解决方法
- Windows系统中可能含有的控制面板文件(并不完全,某些系统可能没有安装部分控制面板工具)
- Perl: class method and instance method
- Studying note of GCC-3.4.6 source (83)
- Oracle函数
- SQL语句快速添加表的记录
- Studying note of GCC-3.4.6 source (84)
- 【行业扫描】马云向温家宝总理专题汇报全文