您的位置:首页 > 产品设计 > UI/UE

Studying note of GCC-3.4.6 source (142 - continue)

2011-01-15 11:06 316 查看
OK. Now let’s see the output
of GCC for our instance 1.

Example 1:

Vtable for C

C::_ZTV1C: 12u entries

0
0u
// vbase offset

4
0u
// vcall offset

8
(int (*)(...))0

12
(int (*)(...))(& _ZTI1C)

16
C
::_ZTcv0_n12_v0_n16_N1C1fEv
// slot for
C::B1::A::f

20
C
::f
// slot for C::f

24
-4u

28
-4u

32
(int (*)(...))-0x000000004

36
(int (*)(...))(& _ZTI1C)

40
C
::_ZTcvn4_n12_v0_n16_N1C1fEv
// slot for C::B2::A::f

44
C
::_ZTchn4_h4_N1C1fEv
// slot for C::B2::f

… // no VTT for A

VTT for B1

B1::_ZTT2B1:
2u entries

0
((& B1::_ZTV2B1) + 16u)

4
((& B1::_ZTV2B1) + 16u)



VTT for B2

B2::_ZTT2B2:
2u entries

0
((& B2::_ZTV2B2) + 16u)

4
((& B2::_ZTV2B2) + 16u)



Construction
vtable for B1 (0xb7f2d980
instance) in C

C::_ZTC1C0_2B1: 6u
entries

0
0u

4
0u

8
(int (*)(...))0

12
(int (*)(...))(& _ZTI2B1)

16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// C::B1::f

20
B1::f

Construction
vtable for B2 (0xb7f2da00
instance) in C

C::_ZTC1C4_2B2: 10u
entries

0
-4u

4
0u

8
(int (*)(...))0

12
(int (*)(...))(& _ZTI2B2)

16
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f

20
B2::f

24
4u

28
(int (*)(...))4

32
(int (*)(...))(& _ZTI2B2)

36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// C::B2::f

VTT for C

C::_ZTT1C: 7u entries

0
((& C::_ZTV1C) + 16u)
// vptr for C

4
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1

8
((& C::_ZTC1C0_2B1) + 16u)
// construction vtable used for B1::A

12
((& C::_ZTC1C4_2B2) + 16u)
// construction vtable used for B2

16
((& C::_ZTC1C4_2B2) + 36u)
// construction vtable used for B2::A

20
((& C::_ZTV1C) + 16u)

// vptr for
secondary vtable of B2

24
((& C::_ZTV1C) + 40u)
// vptr for secondary vtable of A

Constructing VTT is done
by below function.

6829

static
void

6830

build_vtt

(tree t)

in
class.c

6831

{

6832

tree inits;

6833

tree type;

6834

tree vtt;

6835

tree index;

6836

6837

/* Build up the
initializers for the VTT.
*/

6838

inits = NULL_TREE;

6839

index = size_zero_node;

6840

build_vtt_inits
(TYPE_BINFO (t), t, &inits, &index);

6841

6842

/* If we didn't
need a VTT, we're done.
*/

6843

if (!inits)

6844

return
;

6845

6846

/* Figure out the
type of the VTT.
*/

6847

type = build_index_type
(size_int (list_length (inits) - 1));

6848

type = build_cplus_array_type
(const_ptr_type_node, type);

6849

6850

/* Now, build the
VTT object itself.
*/

6851

vtt = build_vtable
(t, get_vtt_name (t), type);

6852

initialize_array
(vtt, inits);

6853

/* Add the VTT to
the vtables list.

*/

6854

TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));

6855

TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;

6856

6857

dump_vtt (t, vtt);

6858

}

So for our example, for class B1, B2 and C, VTT is expected, and its
body is constructed by build_vtt_init

bleow, in which argument binfo

is
the binfo of the most derived class, t

is the most derived class, and index

is
the last index the VTT entries occupied.

6892

static
tree *

6893

build_vtt_inits

(tree binfo, tree t,
tree* inits, tree* index)
in

class.c

6894

{

6895

int i;

6896

tree b;

6897

tree init;

6898

tree secondary_vptrs;

6899

int top_level_p = same_type_p (TREE_TYPE
(binfo), t);

6900

6901

/* We only need VTTs
for subobjects with virtual bases.
*/

6902

if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE
(binfo)))

6903

return
inits;

6904

6905

/* We need to use a
construction vtable if this is not the primary

6906

VTT.
*/

6907

if (!top_level_p)

6908

{

6909

build_ctor_vtbl_group
(binfo, t);

6910

6911

/* Record the
offset in the VTT where this sub-VTT can be found.
*/

6912

BINFO_SUBVTT_INDEX (binfo) = *index;

6913

}

6914

6915

/* Add the address
of the primary vtable for the complete object.

*/

6916

init = binfo_ctor_vtable
(binfo);

6917

*inits = build_tree_list (NULL_TREE, init);

6918

inits = &TREE_CHAIN (*inits);

6919

if (top_level_p)

6920

{

6921

my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);

6922

BINFO_VPTR_INDEX
(binfo) = *index;

6923

}

6924

*index = size_binop (PLUS_EXPR, *index,
TYPE_SIZE_UNIT (ptr_type_node));

6925

6926

/* Recursively add
the secondary VTTs for non-virtual bases.

*/

6927

for
(i = 0; i < BINFO_N_BASETYPES (binfo); ++i)

6928

{

6929

b = BINFO_BASETYPE (binfo, i);

6930

if (!TREE_VIA_VIRTUAL (b))

6931

inits = build_vtt_inits
(BINFO_BASETYPE (binfo, i), t,

6932

inits, index);

6933

}

In previous section, BINFO_VTABLE of the class is set in dfs_accumulate_vtbl_inits

with vtable initializers. It is a PLUS_EXPR specifies the position in the
initializers for the start point of vtable. At line 6916 above, binfo_ctor_vtable

gets this expression from the class.

6865

static
tree

6866

binfo_ctor_vtable

(tree binfo)
in

class.c

6867

{

6868

tree vt;

6869

6870

while
(1)

6871

{

6872

vt = BINFO_VTABLE (binfo);

6873

if (TREE_CODE (vt) == TREE_LIST)

6874

vt = TREE_VALUE (vt);

6875

if (TREE_CODE (vt) == TREE_VEC)

6876

binfo = vt;

6877

else

6878

break
;

6879

}

6880

6881

return
vt;

6882

}

Above at line 6917, init

returned by binfo_ctor_vtable

is built
in a tree_list; and at line 6917, inits

points to the address of chain

field of this tree_list, so in recursion at line 6931, new nodes will be added
into this chain. Above argument index

is the VTT index where the next element
will be replaced (it is also number of bytes), at beginning it is size_zero_node

.

BINFO_VPTR_INDEX holds the index in the VTT where the vptr for the
subobject can be found. For the most derived class C, its vptr is saved at
index 0. And to non-virtual bases, build_ctor_vtbl_group

does below processing.

7098

static
void

7099

build_ctor_vtbl_group

(tree binfo, tree
t)
in

class.c

7100

{

7101

tree list;

7102

tree type;

7103

tree vtbl;

7104

tree inits;

7105

tree id;

7106

tree vbase;

7107

7108

/* See if we've
already created this construction vtable group.

*/

7109

id = mangle_ctor_vtbl_for_type (t, binfo);

7110

if (IDENTIFIER_GLOBAL_VALUE (id))

7111

return
;

7112

7113

my_friendly_assert (!same_type_p (BINFO_TYPE
(binfo), t), 20010124);

7114

/* Build a version
of VTBL (with the wrong type) for use in

7115

constructing the addresses of
secondary vtables in the

7116

construction vtable
group.
*/

7117

vtbl = build_vtable
(t, id, ptr_type_node);

7118

list = build_tree_list (vtbl, NULL_TREE);

7119

accumulate_vtbl_inits
(binfo, TYPE_BINFO (TREE_TYPE (binfo)),

7120

binfo, t, list);

7121

7122

/* Add the vtables
for each of our virtual bases using the vbase in T

7123

binfo.

*/

7124

for
(vbase = TYPE_BINFO (BINFO_TYPE (binfo));

7125

vbase;

7126

vbase = TREE_CHAIN (vbase))

7127

{

7128

tree b;

7129

7130

if (!TREE_VIA_VIRTUAL (vbase))

7131

continue
;

7132

b = copied_binfo
(vbase, binfo);

7133

7134

accumulate_vtbl_inits
(b, vbase, binfo, t, list);

7135

}

7136

inits = TREE_VALUE (list);

7137

7138

/* Figure out the
type of the construction vtable.
*/

7139

type = build_index_type
(size_int (list_length (inits) - 1));

7140

type = build_cplus_array_type
(vtable_entry_type, type);

7141

TREE_TYPE (vtbl) = type;

7142

7143

/* Initialize the
construction vtable.

*/

7144

CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);

7145

initialize_array
(vtbl, inits);

7146

dump_vtable (t, binfo, vtbl);

7147

}

Above at line 7109, mangle_ctor_vtbl_for_type

returns the mangled
name for the vtable for linkage purpose. Assertion following makes sure that
only bases will go into this function. Then a new created vtable object is
wrapped into a tree_list node, and at line 7119 passed to the below function as
the last argument. See rtti_binfo

is the binfo of qualified direct base,
the function will prepare the intializers for the base.

Here accumulate_vtbl_inits

handles the base in
interesting and its non-virtual base in pre-order order, and then the virtual
base in order of appearing within inheritance tree later in build_ctor_vblt_group

.
We reshow related functions in below for convenience.

7159

static
void

7160

accumulate_vtbl_inits
(tree binfo,
in

class.c

7161

tree orig_binfo,

7162

tree rtti_binfo,

7163

tree t,

7164

tree inits)

7165

{

7166

int i;

7167

int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);

7168

7169

my_friendly_assert (same_type_p (BINFO_TYPE
(binfo),

7170

BINFO_TYPE (orig_binfo)),

7171

20000517);

7172

7173

/* If it doesn't
have a vptr, we don't do anything.
*/

7174

if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE
(binfo)))

7175

return
;

7176

7177

/* If we're
building a construction vtable, we're not interested in

7178

subobjects that don't require
construction vtables.
*/

7179

if (ctor_vtbl_p

7180

&& !TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))

7181

&& !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))

7182

return
;

7183

7184

/* Build the
initializers for the BINFO-in-T vtable.

*/

7185

TREE_VALUE (inits)

7186

= chainon (TREE_VALUE (inits),

7187

dfs_accumulate_vtbl_inits

(binfo, orig_binfo,

7188

rtti_binfo, t, inits));

7189

7190

/* Walk the BINFO
and its bases. We walk in preorder so that as we

7191

initialize each vtable we can
figure out at what offset the

7192

secondary vtable lies from the
primary vtable. We can't use

7193

dfs_walk here because we need
to iterate through bases of BINFO

7194

and RTTI_BINFO
simultaneously.
*/

7195

for
(i = 0; i
< BINFO_N_BASETYPES (binfo); ++i)

7196

{

7197

tree base_binfo = BINFO_BASETYPE (binfo,
i);

7198

7199

/* Skip virtual bases.
*/

7200

if (TREE_VIA_VIRTUAL (base_binfo))

7201

continue
;

7202

accumulate_vtbl_inits

(base_binfo,

7203

BINFO_BASETYPE (orig_binfo, i),

7204

rtti_binfo, t,

7205

inits);

7206

}

7207

}

This time, ctor_vtbl_p

at line 7167 above is true as
argument t

always refers to the most derived class but rtti_binfo

should never. And condition at line
7179 filters out base that doesn’t derive from virutal base and non-virtual.

7212

static
tree

7213

dfs_accumulate_vtbl_inits
(tree binfo,
in

class.c

7214

tree orig_binfo,

7215

tree rtti_binfo,

7216

tree t,

7217

tree l)

7218

{

7219

tree inits = NULL_TREE;

7220

tree vtbl = NULL_TREE;

7221

int ctor_vtbl_p = !same_type_p (BINFO_TYPE
(rtti_binfo), t);

7222

7223

if (ctor_vtbl_p

7224

&& TREE_VIA_VIRTUAL (orig_binfo)
&& BINFO_PRIMARY_P (orig_binfo))

7225

{

7226

/* In the
hierarchy of BINFO_TYPE (RTTI_BINFO), this is a

7227

primary virtual base. If it is not the same
primary in

7228

the hierarchy of T, we'll need to generate a
ctor vtable

7229

for it, to place at its location in T. If it
is the same

7230

primary, we still need a VTT entry for the
vtable, but it

7231

should point to the ctor vtable for the base
it is a

7232

primary for within the sub-hierarchy of
RTTI_BINFO.

7233

7234

There are three possible cases:

7235

7236

1) We are in the same place.

7237

2) We are a primary base within a lost primary
virtual base of

7238

RTTI_BINFO.

7239

3) We are primary to something not a base of
RTTI_BINFO.
*/

7240

7241

tree b = BINFO_PRIMARY_BASE_OF (binfo);

7242

tree last = NULL_TREE;

7243

7244

/* First, look
through the bases we are primary to for RTTI_BINFO

7245

or a virtual base.
*/

7246

for
(; b; b
= BINFO_PRIMARY_BASE_OF (b))

7247

{

7248

last = b;

7249

if
(TREE_VIA_VIRTUAL (b) || b == rtti_binfo)

7250

break
;

7251

}

7252

/* If we run out
of primary links, keep looking down our

7253

inheritance chain; we might be an indirect
primary.
*/

7254

if (b == NULL_TREE)

7255

for
(b =
last; b; b = BINFO_INHERITANCE_CHAIN (b))

7256

if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)

7257

break
;

7258

7259

/* If we found RTTI_BINFO, this is case 1. If
we found a virtual

7260

base B and it is a base of
RTTI_BINFO, this is case 2. In

7261

either case, we share our vtable with LAST,
i.e. the

7262

derived-most base within B of which we are a
primary.
*/

7263

if (b == rtti_binfo

7264

||
(b && purpose_member (BINFO_TYPE (b),

7265

CLASSTYPE_VBASECLASSES (BINFO_TYPE
(rtti_binfo)))))

7266

/* Just set our
BINFO_VTABLE to point to LAST, as we may not have

7267

set LAST's BINFO_VTABLE yet. We'll extract
the actual vptr in

7268

binfo_ctor_vtable after everything's been
set up.
*/

7269

vtbl = last;

7270

7271

/* Otherwise, this is case 3 and we get our
own.
*/

7272

}

7273

else if (!BINFO_NEW_VTABLE_MARKED
(orig_binfo))

7274

return
inits;

7275

7276

if (!vtbl)

7277

{

7278

tree index;

7279

int non_fn_entries;

7280

7281

/* Compute the initializer for this
vtable.
*/

7282

inits = build_vtbl_initializer
(binfo, orig_binfo, t, rtti_binfo,

7283

&non_fn_entries);

7284

7285

/* Figure out the
position to which the VPTR should point.

*/

7286

vtbl = TREE_PURPOSE (l);

7287

vtbl = build1
(ADDR_EXPR,

7288

vtbl_ptr_type_node,

7289

vtbl);

7290

TREE_CONSTANT (vtbl) = 1;

7291

index = size_binop (PLUS_EXPR,

7292

size_int (non_fn_entries),

7293

size_int (list_length (TREE_VALUE (l))));

7294

index = size_binop (MULT_EXPR,

7295

TYPE_SIZE_UNIT (vtable_entry_type),

7296

index);

7297

vtbl = build
(PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);

7298

TREE_CONSTANT (vtbl) = 1;

7299

}

7300

7301

if (ctor_vtbl_p)

7302

/* For a
construction vtable, we can't overwrite BINFO_VTABLE.

7303

So, we make a TREE_LIST.
Later, dfs_fixup_binfo_vtbls will

7304

straighten this out.
*/

7305

BINFO_VTABLE (binfo) = tree_cons
(rtti_binfo, vtbl, BINFO_VTABLE (binfo));

7306

else if (BINFO_PRIMARY_P (binfo) &&
TREE_VIA_VIRTUAL (binfo))

7307

inits = NULL_TREE;

7308

else

7309

/* For an
ordinary vtable, set BINFO_VTABLE.
*/

7310

BINFO_VTABLE (binfo) = vtbl;

7311

7312

return
inits;

7313

}

Note that argument orig_binfo

should always refer to the binfo of
the type of base in interesting. And at line 7273 predicate BINFO_NEW_VTABLE_MARKED
returns true if the type has its own vtable. Now rtti_binfo

is the binfo of the
direct base in interesting. In our example, B1, B2 are such bases when handling
C. And t

refers to the binfo of the most derived class, in our example, it is class C. Next
binfo

is the binfo of the base we are processing.

If handles B1 in
accumulate_vtbl_inits

,
in dfs_accumulate_vtbl_inits

,
to orig_binfo

(here it is binfo of B1),
at
line 7224, condition TREE_VIA_VIRTUAL and BINFO_PRIMARY_P are not hold; But at
line 7273, orig_binfo

of course has its own vtable, which breaks the condition. So it will enters IF
block at line 7276, in which the treatment has been seen in previous section
and simliar. As ctor_vtbl_p

is true, code at line 7305 is run, see that binfo

is binfo of B1-in-C, which
has empty BINFO_VTABLE. Because vtable built here is construction vtable, which
can only borrow BINFO_VTABLE temperarily, as result it is built in a tree_list.
Functions cooperative include: binfo_ctor_vtable

, dfs_fixup_binfo_vtbls

.

Exitting from accumulate_vtbl_inits

at line 7119, B1 in C in example 1 should have following
entries in construction vtable (kept in TREE_PURPOSE slot of list

at
line 7118 in
build_ctor_vtbl_group

, and BINFO_VTABLE (binfo of B1-in-C)).

Construction
vtable for B1 (0xb7f2d980
instance) in C

C::_ZTC1C0_2B1: 6u
entries

0
0u

4
0u

8
(int (*)(...))0

12
(int (*)(...))(& _ZTI2B1)

16
B1::_ZTcv0_n12_v0_n16_N2B11fEv
// slot of
B1::A::f

20
B1::f
// slot of B1::f

Then in invoking accumulate_vtbl_inits

at line 7134, binfo

is
binfo of C::B1, and line 7124 fetches the binfo of type B1, so vbase

is
binfo of B1::A, but b

is binfo of C::B1::A, and t

is still type C. They are passed
to dfs_accumulate_vtbl_inits

as the mapping: binfo

(b

),
orig_binfo

(vbase

), rtti_binfo

(binfo

),
and t

(t

).

Next in the function, b

at line 7241 is binfo of C::B1; and last

gets binfo of C::B1 at line 7248. As result, vtbl

is set by the binfo of C::B1
at line 7269. Finally, at line 7305, BINFO_VTABLE(binfo of C::B1::A) is extended
by a tree_list containing binfo of C::B1. And NULL inits

is returned.

However thing is a little different for B2-in-C. Also at exitting
from accumulate_vtbl_inits

at line 7119, B2-in-C in example 1 should have following extra entries in
construction vtable (kept in TREE_PURPOSE slot of list

at line 7118 in build_ctor_vtbl_group

).

Construction
vtable for B2 (0xb7f2da00
instance) in C

C::_ZTC1C4_2B2: 10u
entries

0
-4u

4
0u

8
(int (*)(...))0

12
(int (*)(...))(& _ZTI2B2)

16
B2::_ZTcv0_n12_v0_n16_N2B21fEv

20
B2::f
// slot of B2::f

But in dfs_accumulate_vtbl_inits

for B2::A,
it gets binfo

:
binfo of C::B2 (arg: rtti_binfo

), vbase

: binfo of B2::A (arg: orig_binfo

), b

: binfo of C::B2::A (arg: binfo

),
and t

:
C (arg: t

).

Then b

at line 7241 this time is binfo of C::B2; and last

at line 7248 gets NULL as it
climbs up via path A
à

B1 à

C. So vtbl

keeps NULL in condition at line 7276. Thus the construction vtable generated
for B2::A has below entries:

24
4u
// part of A in B2 - begin

28
(int (*)(...))4

32
(int (*)(...))(& _ZTI2B2)

36
B2::_ZTcv0_n12_v0_n16_N2B21fEv
// part of A
in B2 - end

Line 7140 in build_ctor_vtbl_group

rebuilds the array type for those construction vtables. Next at line 7144, this
construction vtable for base is linked into CLASSTYPE_VTABLES of the most
derived class. And initialize_array

at line 7145 prepares
initializers with exact types for vtable entry.

Return build_vtt_inits

from build_ctor_vtbl_group

, at
line 6916 binfo_ctor_vtable

gets construction vtable from binfo of C::B1 (recorded at index 1).

FOR

block at line 6927 does nothing for B1 or B2, it then arrives below
code.

build_vtt_inits (continue)

6935

/* Add secondary
virtual pointers for all subobjects of BINFO with

6936

either virtual bases or
reachable along a virtual path, except

6937

subobjects that are
non-virtual primary bases.
*/

6938

secondary_vptrs = tree_cons (t, NULL_TREE,
BINFO_TYPE (binfo));

6939

TREE_TYPE (secondary_vptrs) = *index;

6940

VTT_TOP_LEVEL_P (secondary_vptrs) =
top_level_p;

6941

VTT_MARKED_BINFO_P (secondary_vptrs) = 0;

6942

6943

dfs_walk_real
(binfo,

6944

dfs_build_secondary_vptr_vtt_inits
,

6945

NULL,

6946

dfs_ctor_vtable_bases_queue_p,

6947

secondary_vptrs);

6948

VTT_MARKED_BINFO_P (secondary_vptrs) = 1;

6949

dfs_walk (binfo, dfs_unmark,
dfs_ctor_vtable_bases_queue_p,

6950

secondary_vptrs);

6951

6952

*index = TREE_TYPE (secondary_vptrs);

6953

6954

/* The secondary
vptrs come back in reverse order. After we reverse

6955

them, and add the INITS, the
last init will be the first element

6956

of the chain.
*/

6957

secondary_vptrs = TREE_VALUE
(secondary_vptrs);

6958

if (secondary_vptrs)

6959

{

6960

*inits = nreverse (secondary_vptrs);

6961

inits = &TREE_CHAIN (secondary_vptrs);

6962

my_friendly_assert (*inits == NULL_TREE,
20000517);

6963

}

6964

6965

/* Add the
secondary VTTs for virtual bases.
*/

6966

if (top_level_p)

6967

for
(b =
TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))

6968

{

6969

if (!TREE_VIA_VIRTUAL (b))

6970

continue
;

6971

6972

inits = build_vtt_inits
(b, t, inits, index);

6973

}

6974

6975

if (!top_level_p)

6976

{

6977

tree data = tree_cons (t, binfo,
NULL_TREE);

6978

VTT_TOP_LEVEL_P (data) = 0;

6979

VTT_MARKED_BINFO_P (data) = 0;

6980

6981

dfs_walk (binfo, dfs_fixup_binfo_vtbls
,

6982

dfs_ctor_vtable_bases_queue_p,

6983

data);

6984

}

6985

6986

return
inits;

6987

}

Above secondary_vptrs

as indicates by its name, is the pointer to secondary vtable in the VTT of the
most derived class (that is C for our example); and index

tells the slot of the VTT
this pointer lies in. The transverse at line 6943, begins at the binfo of base
referred by binfo

(here, i.e., either binfo of C::B1 or binfo of C::B2) and steps into this node.
Routine below then processes the nodes visited in pre-order, see argument data

is secondary_vptrs

.

6996

static
tree

6997

dfs_build_secondary_vptr_vtt_inits

(tree
binfo, void* data)
in

class.c

6998

{

6999

tree l;

7000

tree t;

7001

tree init;

7002

tree index;

7003

int top_level_p;

7004

7005

l = (tree) data;

7006

t = TREE_CHAIN (l);

7007

top_level_p = VTT_TOP_LEVEL_P (l);

7008

7009

BINFO_MARKED (binfo) = 1;

7010

7011

/* We don't care
about bases that don't have vtables.
*/

7012

if (!TYPE_VFIELD (BINFO_TYPE (binfo)))

7013

return
NULL_TREE;

7014

7015

/* We're only
interested in proper subobjects of T.
*/

7016

if (same_type_p (BINFO_TYPE (binfo), t))

7017

return
NULL_TREE;

7018

7019

/* We're not
interested in non-virtual primary bases.

*/

7020

if (!TREE_VIA_VIRTUAL (binfo) &&
BINFO_PRIMARY_P (binfo))

7021

return
NULL_TREE;

7022

7023

/* If BINFO has
virtual bases or is reachable via a virtual path

7024

from T, it'll have a
secondary vptr.
*/

7025

if (!TYPE_USES_VIRTUAL_BASECLASSES
(BINFO_TYPE (binfo))

7026

&& !binfo_via_virtual (binfo, t))

7027

return
NULL_TREE;

7028

7029

/* Record the index
where this secondary vptr can be found.

*/

7030

index = TREE_TYPE (l);

7031

if (top_level_p)

7032

{

7033

my_friendly_assert (!BINFO_VPTR_INDEX
(binfo), 20010129);

7034

BINFO_VPTR_INDEX
(binfo) = index;

7035

}

7036

TREE_TYPE (l) = size_binop (PLUS_EXPR, index,

7037

TYPE_SIZE_UNIT (ptr_type_node));

7038

7039

/* Add the
initializer for the secondary vptr itself.

*/

7040

if (top_level_p && TREE_VIA_VIRTUAL
(binfo))

7041

{

7042

/* It's a primary virtual base, and this is
not the construction

7043

vtable. Find the base this
is primary of in the inheritance graph,

7044

and use that base's vtable
now.
*/

7045

while
(BINFO_PRIMARY_BASE_OF (binfo))

7046

binfo = BINFO_PRIMARY_BASE_OF (binfo);

7047

}

7048

init =
binfo_ctor_vtable

(binfo);

7049

TREE_VALUE (l) = tree_cons (NULL_TREE, init,
TREE_VALUE (l));

7050

7051

return
NULL_TREE;

7052

}

When iterating sub-tree headed by binfo of C::B1, top_level_p

above is false, t

at line 7006 is the type of B1. This node is skipped as condition at line 7016
is hold; At visiting binfo of C::B1::A, as in binfo BINFO_VTABLE of C::B1::A is
the binfo of C::B1, at line 7048 binfo_ctor_vtable

gets construction vtable of
C::B1 again (kept at index 2). Note this function always returns NULL which
forces a full walk within the (sub-)tree. To C::B2, it gets nothing too.

Remember in dfs_accumulate_vtbl_inits

at line 7305,
construction vtable temperarily stays in BINFO_VTABLE. Now construction vtable
has been recorded into VTT, no needs rely upon BINFO_VTABLE any more. Now it is
time to restore BINFO_VTABLE. Pay attention to the constructing of its argument
data. Here, node temperarily appended by C::B1::A is removed (it is C::B2::A
for C::B2).

7075

static
tree

7076

dfs_fixup_binfo_vtbls

(tree binfo, void*
data)
in

class.c

7077

{

7078

BINFO_MARKED (binfo) = 0;

7079

7080

/* We don't care
about bases that don't have vtables.
*/

7081

if (!TYPE_VFIELD (BINFO_TYPE (binfo)))

7082

return
NULL_TREE;

7083

7084

/* If we scribbled
the construction vtable vptr into BINFO, clear it

7085

out now.
*/

7086

if (BINFO_VTABLE (binfo)

7087

&& TREE_CODE (BINFO_VTABLE (binfo))
== TREE_LIST

7088

&& (TREE_PURPOSE (BINFO_VTABLE
(binfo))

7089

== TREE_VALUE ((tree) data)))

7090

BINFO_VTABLE (binfo) = TREE_CHAIN
(BINFO_VTABLE (binfo));

7091

7092

return
NULL_TREE;

7093

}

In treatment of C::B2 mentioned above, when back build_vtt_inits

from build_ctor_vtbl_group

,
its construction vtable is saved in VTT by index 3. Then in dfs_build_secondary_vptr_vtt_inits

for C::B2, binfo_ctor_vtable

at line 7048 gets construction vtable of B2::A (at index 4 in VTT).

After finishes handling B1 and B2, it continues on handling C at
line 6938 in build_vtt_inits

.
It begins to transerve inheritance tree rooted by C at line 6943. So dfs_build_secondary_vptr_vtt_inits

in, top_level_p

is true, and t

is the most derived class C.
During this pre-order walk, C satisfies condtion at line 7016, C::B1 meets
condition at line 7020, and exit the function. For C::B2, index 5 in VTT is set as vptr of C::B2, and its
vtable’s (it’s a secondary vtable) initializer is what we got in previous
section; similarly for C::B1::A, its vptr is in VTT with index 6, also its
vtable’s (secondary vtable too) initialzier is what in BINFO_VTABLE(A-in-C)
prepared in previous section. At last, C::B2::A is skipped, as A has been
visited via C::B1::A.

A is processed in build_vtt_inits

at line 6972 at last, as A
hasn’t virtual base, build_vtt_inits

does nothing.

Returns build_vtt

,
if success, inits

should not be NULL. Following builds appropriate type for VTT and constructs
its static object, then links this object into head of CLASSTYPE_VTABLES of the
most derived class.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: