Studying note of GCC-3.4.6 source (85)

5.9.2.2.    If accessible from friends

If protected_accessible_p return nonzero, the derived tree of current class contains decl, and type must be its base (guaranteed by block at line 837 in protected_accessible_p), then it can directly go to check the accessibility from type, and it is OK with level no lower than protected. Otherwise, if the derived tree of current class doesn’t contain decl, or type isn’t its base, then it needs to see if current scope is a friend that can access decl. Parameter scope of friend_accessible_p is gotten by below 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  }

 

The setting of current_class_type and current_function_decl is given as following.

 

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

*: include class’s friend. **: GNU’s extension, local class within function

Now the case needs be covered is: class accepting current scope (class, or function) as friend contains decl, and type is one of its bases. In friend_accessible_p, parameter binfo comes from 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  }

 

Above befriending_classes is the list of classes acceptting current class or function as friend. If for these classes, protected_accessible_p still returns 0, if scope is a class, then here it checks class containing scope one level up and up; while if scope is a funcction, then checks the case its containing class being a friend. Line 893 indicates a function template, DECL_TI_TEMPLATE is the node for its instantiation or specialization. And line 904 finds a class template, CLASSTYPE_TI_TEMPLATE is the node for its instantiation or specialization. Here checks if the specialization is the expected friend.

5.9.2.3.    Determine accessibility

From above, if protected_accessible_p or friend_accessible_p returns nonzero, means decl and type are within the same derived tree. Then next, in accessible_p at line 1000, access_in_type is invoked to check the accessibility decl of from type. If it finds the result is above protected, of course type can access decl. But for friend, even private isn’t a problem. So if the result is private, it still needs to see if it is a friend. Further, there is even more complex case, for example:

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

}

It is searched by dfs_accessible_p during traversing the derived tree of type by post-ordered. BINFO_ACCESS has been set at time access_in_type at line 1000 running. If it is ak_none, it means type is unrelated to 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  }

 

Likely, dfs_accessible_queue_p is the function ran in in-order and returns qualified binfo for stepping into.

 

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  }

 

This time, as long as finding out a matched type, it exits the traversal.

 

你可能感兴趣的:(function,tree,Class,processing,Access,Instantiation)