您的位置:首页 > 编程语言

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

2010-11-05 10:00 465 查看
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
部分。它与我们在前面章节所看到处理过程几乎一样。这里我们跳过它。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: