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

5.12.4.2.3.2.  base-clause 构建节点

注意参数 base 在我们的例子中指向的 BOUND_TEMPLATE_TEMPLATE_PARM 节点, access access_public_node

 

2242   tree

2243   finish_base_specifier (tree base, tree access, bool virtual_p)                 in semantics.c

2244   {

2245     tree result;

2246  

2247     if (base == error_mark_node)

2248     {

2249       error ("invalid base-class specification");

2250       result = NULL_TREE;

2251     }

2252     else if (! is_aggr_type (base, 1))

2253       result = NULL_TREE;

2254     else

2255     {

2256       if (cp_type_quals (base) != 0)

2257       {

2258         error ("base class `%T' has cv qualifiers", base);

2259         base = TYPE_MAIN_VARIANT (base);

2260       }

2261       result = build_tree_list (access, base);

2262       TREE_VIA_VIRTUAL (result) = virtual_p;

2263     }

2264  

2265     return result;

2266   }

 

在为基类构建了节点后,在前端中这些基类被串接在一起来代表 base-clause

5.12.4.2.3.2.1.          填充 binfo

cp_parser_base_clause 返回,在 cp_parser_class_head 12339 行,由 bases 指向先前所构建的节点 BOUND_TEMPLATE_TEMPLATE_PARM ,而 type 则是代表“ SmallObject ”的 RECORD_TYPE 。记得在构建这个 RECORD_TYPE 时,还构建了一个空的 binfo 节点。现在这个节点将根据刚才解析的 base-clause 来填充。

 

9615   void

9616   xref_basetypes (tree ref, tree base_list)                                                             in decl.c

9617   {

9618     /* In the declaration `A : X, Y, ... Z' we mark all the types

9619       (A, X, Y, ..., Z) so we can check for duplicates.  */

9620     tree *basep;

9621  

9622     int i;

9623     enum tag_types tag_code;

9624  

9625     if (ref == error_mark_node)

9626       return ;

9627  

9628     if (TREE_CODE (ref) == UNION_TYPE)

9629     {

9630       error ("derived union `%T' invalid", ref);

9631       return ;

9632     }

9633  

9634     tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);

9635  

9636     /* First, make sure that any templates in base-classes are

9637       instantiated. This ensures that if we call ourselves recursively

9638       we do not get confused about which classes are marked and which

9639       are not.  */

9640     basep = &base_list;

9641     while (*basep)

9642     {

9643       tree basetype = TREE_VALUE (*basep);

9644       if (!(processing_template_decl && uses_template_parms (basetype))

9645           && !complete_type_or_else (basetype, NULL))

9646         /* An incomplete type. Remove it from the list.  */

9647         *basep = TREE_CHAIN (*basep);

9648       else

9649         basep = &TREE_CHAIN (*basep);

9650     }

9651  

9652     SET_CLASSTYPE_MARKED (ref);

9653     i = list_length (base_list);

9654     if (i)

9655     {

9656       tree binfo = TYPE_BINFO (ref);

9657       tree binfos = make_tree_vec (i);

9658       tree accesses = make_tree_vec (i);

9659        

9660       BINFO_BASETYPES (binfo) = binfos;

9661       BINFO_BASEACCESSES (binfo) = accesses;

9662    

9663       for (i = 0; base_list; base_list = TREE_CHAIN (base_list))

9664       {

9665         tree access = TREE_PURPOSE (base_list);

9666         int via_virtual = TREE_VIA_VIRTUAL (base_list);

9667         tree basetype = TREE_VALUE (base_list);

9668          tree base_binfo;

9669         

9670         if (access == access_default_node)

9671            /* The base of a derived struct is public by default.  */

9672           access = (tag_code == class_type

9673                   ? access_private_node : access_public_node);

9674         

9675         if (basetype && TREE_CODE (basetype) == TYPE_DECL)

9676           basetype = TREE_TYPE (basetype);

9677         if (!basetype

9678            || (TREE_CODE (basetype) != RECORD_TYPE

9679              && TREE_CODE (basetype) != TYPENAME_TYPE

9680              && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM

9681              && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))

9682         {

9683           error ("base type `%T' fails to be a struct or class type",

9684                 basetype);

9685           continue ;

9686         }

9687         

9688         if (CLASSTYPE_MARKED (basetype))

9689         {

9690           if (basetype == ref)

9691             error ("recursive type `%T' undefined", basetype);

9692           else

9693             error ("duplicate base type `%T' invalid", basetype);

9694           continue ;

9695         }

9696         

9697         if (TYPE_FOR_JAVA (basetype)

9698            && (current_lang_depth () == 0))

9699           TYPE_FOR_JAVA (ref) = 1;

9700         

9701         if (CLASS_TYPE_P (basetype))

9702          {

9703           base_binfo = TYPE_BINFO (basetype);

9704            /* This flag will be in the binfo of the base type, we must

9705              clear it after copying the base binfos.  */

9706            BINFO_DEPENDENT_BASE_P (base_binfo)

9707                 = dependent_type_p (basetype);

9708         }

9709         else

9710           base_binfo = make_binfo (size_zero_node, basetype,

9711                                 NULL_TREE, NULL_TREE);

9712         

9713         TREE_VEC_ELT (binfos, i) = base_binfo;

9714         TREE_VEC_ELT (accesses, i) = access;

9715         /* This flag will be in the binfo of the base type, we must

9716           clear it after copying the base binfos.  */

9717         TREE_VIA_VIRTUAL (base_binfo) = via_virtual;

9718         

9719         SET_CLASSTYPE_MARKED (basetype);

9720         

9721          /* We are free to modify these bits because they are meaningless

9722           at top level, and BASETYPE is a top-level type.  */

9723         if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))

9724         {

9725           TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;

9726            /* Converting to a virtual base class requires looking

9727              up the offset of the virtual base.  */

9728            TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;

9729         }

9730         

9731         if (CLASS_TYPE_P (basetype))

9732         {

9733           TYPE_HAS_NEW_OPERATOR (ref)

9734               |= TYPE_HAS_NEW_OPERATOR (basetype);

9735           TYPE_HAS_ARRAY_NEW_OPERATOR (ref)

9736               |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);

9737           TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);

9738           /* If the base-class uses multiple inheritance, so do we.  */

9739           TYPE_USES_MULTIPLE_INHERITANCE (ref)

9740               |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);

9741           /* Likewise, if converting to a base of the base may require

9742             code, then we may need to generate code to convert to a

9743             base as well.  */

9744            TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)

9745               |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);

9746         }

9747         i++;

9748       }

9749       if (i)

9750         TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;

9751       else

9752         BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;

9753        

9754       if (i > 1)

9755       {

9756         TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;

9757         /* If there is more than one non-empty they cannot be at the same

9758            address.  */

9759         TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;

9760       }

9761     }

9762    

9763     /* Copy the base binfos, collect the virtual bases and set the

9764       inheritance order chain.  */

9765     copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);

9766     CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));

9767  

9768     if (TYPE_FOR_JAVA (ref))

9769     {

9770       if (TYPE_USES_MULTIPLE_INHERITANCE (ref))

9771         error ("Java class '%T' cannot have multiple bases", ref);

9772       if (CLASSTYPE_VBASECLASSES (ref))

9773         error ("Java class '%T' cannot have virtual bases", ref);

9774     }

9775  

9776     /* Unmark all the types.  */

9777     while (i--)

9778     {

9779       tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));

9780        

9781       CLEAR_CLASSTYPE_MARKED (basetype);

9782       if (CLASS_TYPE_P (basetype))

9783       {

9784         TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;

9785         BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;

9786       }

9787     }

9788     CLEAR_CLASSTYPE_MARKED (ref);

9789   }

 

注意在 9645 行,在 base-clause 不能出现未完成的类。而在 9765 行,基类本身有可能从其他类派生,因此需要深拷贝所有相关的 binfo 。看到对于指定的类, binfo 节点,以深度优先、由左至右为序,形成了一个链表。

 

577    tree

578    copy_base_binfos (tree binfo, tree t, tree prev)                                                         in tree.c

579    {

580      tree binfos = BINFO_BASETYPES (binfo);

581      int n, ix;

582   

583      if (prev)

584        TREE_CHAIN (prev) = binfo;

585      prev = binfo;

586     

587      if (binfos == NULL_TREE)

588        return prev;

589   

590      n = TREE_VEC_LENGTH (binfos);

591     

592      /* Now copy the structure beneath BINFO.  */

593      for (ix = 0; ix != n; ix++)

594      {

595        tree base_binfo = TREE_VEC_ELT (binfos, ix);

596        tree new_binfo = NULL_TREE;

597   

598        if (!CLASS_TYPE_P (BINFO_TYPE (base_binfo)))

599        {

600          my_friendly_assert (binfo == TYPE_BINFO (t), 20030204);

601          

602          new_binfo = base_binfo;

603          TREE_CHAIN (prev) = new_binfo;

604          prev = new_binfo;

605          BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;

606          BINFO_DEPENDENT_BASE_P (new_binfo) = 1;

607        }

608        else if (TREE_VIA_VIRTUAL (base_binfo))

609        {

610          new_binfo = purpose_member (BINFO_TYPE (base_binfo),

611                                     CLASSTYPE_VBASECLASSES (t));

612          if (new_binfo)

613            new_binfo = TREE_VALUE (new_binfo);

614        }

615         

616        if (!new_binfo)

617        {

618          new_binfo = make_binfo (BINFO_OFFSET (base_binfo),

619                                base_binfo, NULL_TREE,

620                                BINFO_VIRTUALS (base_binfo));

621          prev = copy_base_binfos (new_binfo, t, prev);

622          if (TREE_VIA_VIRTUAL (base_binfo))

623          {

624            CLASSTYPE_VBASECLASSES (t)

625                = tree_cons (BINFO_TYPE (new_binfo), new_binfo,

626                            CLASSTYPE_VBASECLASSES (t));

627            TREE_VIA_VIRTUAL (new_binfo) = 1;

628            BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);

629          }

630          else

631            BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;

632        }

633        TREE_VEC_ELT (binfos, ix) = new_binfo;

634      }

635   

636      return prev;

637    }

 

虚拟继承是例外,在这个情形下,被虚拟继承的基类只能有一个实例出现在派生树中。因此如果该实例已经存在,创建一个引用而不是拷贝(注意每个类都有自己的派生树)。例如:

class A { … };

class B: virtual public A { … };

class C: virtual public A { … };

class D: public B, C { … };

在类 D 中,仅含有一个 A binfo 。而在类 B C 中,同样都有一个 A binfo (类 D C B 具有不同的派生树,在 D 的派生树中,有 C B binfo 的拷贝)。

注意到对于 BOUND_TEMPLATE_TEMPLATE_PARM. 节点, CLASS_TYPE_P 返回 false 。这是隐含构建的聚合类型,不需要真正的拷贝。那么“ SmallObject ”和“ ThreadingModel ”的 binfo 填充如下。

点此打开

114 :填充 binfo

5.12.4.3.              解析 class-definition

那么接下来,解析器将处理 class-definition 部分。它与我们在前面章节所看到处理过程几乎一样。这里我们跳过它。

 

你可能感兴趣的:(list,tree,null,Class,Access,inheritance)