Studying note of GCC-3.4.6 source (141 - cont 1)
2011-01-09 17:30
423 查看
When finishing handling of B1, build_vcall_and_vbase_vtbl_entries
returns to
the invocation of handling class C. This time build_vbase_offset_vtbl_entries
does nothing, as base A has been processed with BINFO_VTABLE_PATH_MARKED set. And
in build_vcall_offset_vtbl_entries
,
vid->generate_vcall_entries
is set in false for class C, and vid->vbase
is set to binfo of C. Below call
stack would be involved.
build_vcall_and_vbase_vtbl_entries:
for C
build_vcall_offset_vtbl_entries:
for C
add_vcall_offset_vtbl_entries_r:
for C
add_vcall_offset_vtbl_entries_r:
for B1
add_vcall_offset_vtbl_entries_r:
for A
add_vcall_offset_vtbl_entries_1:
for B1
add_vcall_offset:
for B1
add_vcall_offset_vtbl_entries_1:
for C
add_vcall_offset:
for C
add_vcall_offset_vtbl_entries_r:
for B2
add_vcall_offset_vtbl_entries_r:
for A
add_vcall_offset_vtbl_entries_1:
for B2
add_vcall_offset:
for B2
In above call
stack, add_vcall_offset_vtbl_entries_r
first recurses for C’s A, but it does nothing as condition at line 7680
satisified. In following add_vcall_offset
, vid->fns now holds
virtual functions seen above, so same_signature_p
at
line 7805 returns true for B1’s
virtual, and exits the function at line 7810. After returning from add_vcall_offset_vtbl_entries_r
handling B1, invoking add_vcall_offset_vtbl_entries_1
for C.
Similiarly, same_signature_p
returns true for C’s virtual. Then add_vcall_offset_vtbl_entries_r
at line 7698
is recursed for B2 (the non-primary base), it’s original primary base A is
filtered out by conidtion at line 7680, also in add_vcall_offset
, same_signature_p
returns true for B2’s virtual.
When exitting
from build_vcall_and_vbase_vtbl_entries
for C, we will get following vtable initializers and CLASSTYPE_VCALL_INDICES.
In above figure, in the
chain of CLASSTYPE_VCALL_INDICES, value
field of node A::f is -3; it coordinate
with A::f given in chain of last_init.
Back build_vtbl_initializer
, it is still handling
C.
build_vtbl_initializer (continue)
7378
/* If the target
requires padding between data entries, add that now.
*/
7379
if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
7380
{
…
7395
}
7396
7397
if (non_fn_entries_p)
7398
*non_fn_entries_p = list_length
(vid.inits);
7399
7400
/* Go through all
the ordinary virtual functions, building up
7401
initializers.
*/
7402
vfun_inits = NULL_TREE;
7403
for
(v =
BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
7404
{
7405
tree delta;
7406
tree vcall_index;
7407
tree fn, fn_original;
7408
tree init = NULL_TREE;
7409
7410
fn = BV_FN (v);
7411
fn_original = fn;
7412
if (DECL_THUNK_P (fn))
7413
{
7414
if (!DECL_NAME (fn))
7415
finish_thunk
(fn);
7416
if (THUNK_ALIAS (fn))
7417
{
7418
fn = THUNK_ALIAS (fn);
7419
BV_FN (v) = fn;
7420
}
7421
fn_original = THUNK_TARGET (fn);
7422
}
7423
7424
/* If the only
definition of this function signature along our
7425
primary base chain is from a
lost primary, this vtable slot will
7426
never be used, so just zero
it out. This is important to avoid
7427
requiring extra thunks which
cannot be generated with the function.
7428
7429
We first check this in
update_vtable_entry_for_fn, so we handle
7430
restored primary bases
properly; we also need to do it here so we
7431
zero out unused slots in
ctor vtables, rather than filling themff
7432
with erroneous values
(though harmless, apart from relocation
7433
costs).
*/
7434
for
(b = binfo;
; b = get_primary_binfo
(b))
7435
{
7436
/* We found a
defn before a lost primary; go ahead as normal.
*/
7437
if (look_for_overrides_here
(BINFO_TYPE (b), fn_original))
7438
break
;
7439
7440
/* The nearest
definition is from a lost primary; clear the
7441
slot.
*/
7442
if (BINFO_LOST_PRIMARY_P (b))
7443
{
7444
init = size_zero_node;
7445
break
;
7446
}
7447
}
7448
7449
if (! init)
7450
{
7451
/* Pull the
offset for `this', and the function to call, out of
7452
the list.
*/
7453
delta = BV_DELTA (v);
7454
vcall_index
= BV_VCALL_INDEX (v);
7455
7456
my_friendly_assert (TREE_CODE (delta) ==
INTEGER_CST, 19990727);
7457
my_friendly_assert (TREE_CODE (fn) ==
FUNCTION_DECL, 19990727);
7458
7459
/* You can't
call an abstract virtual function; it's abstract.
7460
So, we replace these functions
with __pure_virtual.
*/
7461
if (DECL_PURE_VIRTUAL_P (fn_original))
7462
fn = abort_fndecl;
7463
else if (!integer_zerop
(delta) || vcall_index)
7464
{
7465
fn = make_thunk
(fn, /*this_adjusting=*/
1, delta,
vcall_index);
7466
if (!DECL_NAME (fn))
7467
finish_thunk
(fn);
7468
}
7469
/* Take the
address of the function, considering it to be of an
7470
appropriate generic
type.
*/
7471
init = build1
(ADDR_EXPR, vfunc_ptr_type_node
,
fn);
7472
/* The address
of a function can't change.
*/
7473
TREE_CONSTANT (init) = 1;
7474
}
7475
7476
/* And add it to
the chain of initializers.
*/
7477
if (TARGET_VTABLE_USES_DESCRIPTORS)
7478
{
…
7493
}
7494
else
7495
vfun_inits = tree_cons (NULL_TREE, init,
vfun_inits);
7496
}
7497
7498
/* The initializers
for virtual functions were built up in reverse
7499
order; straighten them out
now.
*/
7450
vfun_inits = nreverse (vfun_inits);
7451
7452
/* The negative
offset initializers are also in reverse order.
*/
7453
vid.inits = nreverse (vid.inits);
7454
7455
/* Chain the two
together.
*/
7456
return
chainon (vid.inits, vfun_inits);
7457
}
Above orig_binfo
comes from current class, whose BINFO_VIRTUALS has been process by update_vtable_entry_for_fn
(see previous section). Virtuals in BINFO_VIRTUALS can be a thunk, which is
constructed in update_vtable_entry_for_fn
, and only of result-adjustmnet.
Here it is constructing this-adjustment thunk, and information BV_DELTA, BV_VCALL_INDEX
(from CLASSTYPE_VCALL_INDICES of the virtual base. Above can see C also
prepared it for future being virtual base) is also collected by update_vtable_entry_for_fn
.
Now all thunks are still anonymous. In the front-end, that indicates
the thunk is incomplete.
194
void
195
finish_thunk
(tree thunk)
in
method.c
196
{
197
tree function, name;
198
tree fixed_offset = ssize_int
(THUNK_FIXED_OFFSET (thunk));
199
tree virtual_offset = THUNK_VIRTUAL_OFFSET
(thunk);
200
201
my_friendly_assert (!DECL_NAME (thunk)
&& DECL_THUNK_P (thunk), 20021127);
202
if (virtual_offset &&
DECL_RESULT_THUNK_P (thunk))
203
virtual_offset = BINFO_VPTR_FIELD
(virtual_offset);
204
function = THUNK_TARGET (thunk);
205
name = mangle_thunk (function,
DECL_THIS_THUNK_P (thunk),
206
fixed_offset, virtual_offset);
207
208
/* We can end up
with declarations of (logically) different
209
covariant thunks,
that do identical adjustments. The two thunks
210
will be adjusting
between within different hierarchies, which
211
happen to have
the same layout. We must nullify one of them to
212
refer to the
other.
*/
213
if (DECL_RESULT_THUNK_P (thunk))
214
{
215
tree cov_probe;
216
217
for
(cov_probe = DECL_THUNKS (function);
218
cov_probe; cov_probe = TREE_CHAIN
(cov_probe))
219
if (DECL_NAME (cov_probe) == name)
220
{
221
my_friendly_assert (!DECL_THUNKS (thunk),
20031023);
222
THUNK_ALIAS (thunk) = (THUNK_ALIAS
(cov_probe)
223
? THUNK_ALIAS (cov_probe) : cov_probe);
224
break
;
225
}
226
}
227
228
DECL_NAME (thunk) = name;
229
SET_DECL_ASSEMBLER_NAME (thunk, name);
230
}
THUNK_VIRTUAL_OFFSET, for this-adjusting thunk, it is the number of
bytes to be added to the vtable to find the vcall offset; for a result
adjusting thunk, it is the binfo of the relevant virtual base. BINFO_VPTR_FIELD
at line 203 is an INTEGER_CST giving an offset into the vtable where the offset
to the virtual base can be found. So for result adjusting thunk, needs
treatment at line 203 to get the offset of the virtual base. At line 205, mangle_thunk
returns the mangled name for the thunk (at section beginning, we have seen
examples of thunk’s mangled name). After setting the name with the thunk, it
can be regarded as finished. As thunk’s name is constructed by its action, it’s
possible there exists thunk of same name, at which treats the thunk built later
as the alias of the former one, they share the same thunk function.
dfs_accumulate_vtbl_inits
(continue)
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
}
Back to dfs_accumulate_vtbl_inits
, note that we are
still handling class C. above l
is list
in finish_vtbls
, in its TREE_PURPOSE is the TYPE_BINFO_VTABLE
(vtable saved in the binfo of the type, which is VAR_DECL generated by build_primary_vtable
).
And originally, TREE_VALUE of l
is NULL (but at line 7185 in accumulate_vtbl_inits
, it chains l
with
the list returned by dfs_accumulate_vtbl_inits
). See that non_fn_entries
records the number of entries of negative index. So it can know where to begin
the entries visible to programmer.
When returns back to accumulate_vtbl_inits
, after chaining into list
in finish_vtt
,
we get following figure (remember in create_vtable_ptr
, every virtual function has
an extra node generated with 0 delta).
Next, in accumulate_vtbl_inits
,
at line 7195, in FOR
block, binfo B1
within C is not handled as its BINFO_NEW_VTABLE_MARKED unset (see dfs_accumulate_vtbl_inits
line 7273). While for B2 in
C, it has secondary vtable generated, so passes the line successfully. At that
time, ctor_vtbl_p
is false, binfo
from class B2, orig_binfo
from B2 in C, and rtti_binfo
is C’s binfo, it undergoes similar processing as that for C above. Then when
back finish_vtbls
,
A in C is processed by accumulate_vtbl_inits
at
line 6780, in which ctor_vtbl_p
is still false. But this A hasn’t
flag BINFO_NEW_VTABLE_MARKED set, so exits dfs_accumulate_vtbl_inits
immediately.
So before
invoking initialize_vtable
at line 6784, list
is given in below figure.
(Click
here for open
)
Figure 117
: initializer for vtable
Above B1 and A don’t have their part of vtable as they share the
same part with C.
In below function, now argument inits
is the chain referred by value slot of list
in
above figure. This chain holds all initializers for class C’s vtable. Note that
at last vtbl
at line 7297 in dfs_accumulate_vtbl_inits
,
points to the start point of vtable of specified class which is a PLUS_EXPR of
vtbl+4 for C, vtbl+8 for base B2.
6789
static
void
6790
initialize_vtable
(tree binfo, tree
inits)
in
class.c
6791
{
6792
tree decl;
6793
6794
layout_vtable_decl
(binfo, list_length (inits));
6795
decl = get_vtbl_decl_for_binfo
(binfo);
6796
initialize_array
(decl, inits);
6797
dump_vtable (BINFO_TYPE (binfo), binfo, decl);
6798
}
Originally in build_vtable
, vtable is created as type of vtbl_type_node
which is the array of type vtable_entry_type
with empty dimension. Now the
size of the array is settled down, we can create the exact type by layout_vtable_decl
.
1778
static
void
1779
layout_vtable_decl
(tree binfo, int n)
in
class.c
1780
{
1781
tree atype;
1782
tree vtable;
1783
1784
atype = build_cplus_array_type (vtable_entry_type
,
1785
build_index_type
(size_int (n - 1)));
1786
layout_type
(atype);
1787
1788
/* We may have to
grow the vtable.
*/
1789
vtable = get_vtbl_decl_for_binfo
(binfo);
1790
if (!same_type_p (TREE_TYPE (vtable), atype))
1791
{
1792
TREE_TYPE (vtable) = atype;
1793
DECL_SIZE (vtable) = DECL_SIZE_UNIT
(vtable) = NULL_TREE;
1794
layout_decl
(vtable, 0);
1795
}
1796
}
So at line 6795, the vtable VAR_DECL fetched has correct type
defined. And it is passed as argument decl
in below function.
6803
static
void
6804
initialize_array
(tree decl, tree inits)
in
class.c
6805
{
6806
tree context;
6807
6808
context = DECL_CONTEXT (decl);
6809
DECL_CONTEXT (decl) = NULL_TREE;
6810
DECL_INITIAL (decl) = build_constructor
(NULL_TREE, inits);
6811
TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) =
1;
6812
cp_finish_decl
(decl, DECL_INITIAL (decl), NULL_TREE, 0);
6813
DECL_CONTEXT (decl) = context;
6814
}
See node of CONSTRUCTOR is built for initializing this VAR_DECL.
Note that this node has empty type
field (it is treated as unknown).
444
tree
445
build_constructor
(tree type, tree vals)
in
tree.c
446
{
447
tree c = make_node
(CONSTRUCTOR);
448
TREE_TYPE (c) = type;
449
CONSTRUCTOR_ELTS (c) = vals;
450
451
/* ??? May not be
necessary. Mirrors what build does.
*/
452
if (vals)
453
{
454
TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS
(vals);
455
TREE_READONLY (c) = TREE_READONLY (vals);
456
TREE_CONSTANT (c) = TREE_CONSTANT (vals);
457
}
458
else
459
TREE_CONSTANT (c) = 0;
/* safe side */
460
461
return
c;
462
}
Being a VAR_DECL, it is completed by cp_finish_decl
. Note that we
are still within another cp_finish_decl
for the template instantiation
of SmallObject.
4768
void
4769
cp_finish_decl
(tree decl, tree init,
tree asmspec_tree, int flags)
in decl.c
4770
{
4771
tree type;
4772
tree ttype = NULL_TREE;
4773
tree cleanup;
4774
const
char
*asmspec = NULL;
4775
int was_readonly = 0;
4776
bool var_definition_p = false;
4777
4778
if (decl == error_mark_node)
4779
return
;
4780
else if (! decl)
4781
{
4782
if (init)
4783
error ("assignment (not
initialization) in declaration");
4784
return
;
4785
}
4786
4787
my_friendly_assert (TREE_CODE (decl) !=
RESULT_DECL, 20030619);
4788
4789
/* Assume no
cleanup is required.
*/
4790
cleanup = NULL_TREE;
4791
4792
/* If a name was
specified, get the string.
*/
4793
if (global_scope_p (current_binding_level
))
4794
asmspec_tree = maybe_apply_renaming_pragma
(decl, asmspec_tree);
4795
if (asmspec_tree)
4796
asmspec = TREE_STRING_POINTER
(asmspec_tree);
4797
4798
if (init && TREE_CODE (init) ==
NAMESPACE_DECL)
4799
{
4800
error ("cannot initialize `%D' to
namespace `%D'",
4802
decl, init);
4803
init = NULL_TREE;
4804
}
4805
4806
if (current_class_type
4807
&& CP_DECL_CONTEXT (decl) == current_class_type
4808
&& TYPE_BEING_DEFINED (current_class_type
)
4809
&& (DECL_INITIAL (decl) || init))
4810
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
4811
4812
if (TREE_CODE (decl) == VAR_DECL
4813
&& DECL_CONTEXT (decl)
4814
&& TREE_CODE (DECL_CONTEXT (decl))
== NAMESPACE_DECL
4815
&& DECL_CONTEXT (decl) != current_namespace
4816
&& init)
4817
{
4818
/* Leave the namespace of the object.
*/
4819
pop_decl_namespace ();
4820
}
4821
4822
type = TREE_TYPE (decl);
4823
4824
if (type == error_mark_node)
4825
goto
finish_end0;
4826
4827
if (TYPE_HAS_MUTABLE_P (type))
4828
TREE_READONLY (decl) = 0;
4829
4830
if (processing_template_decl
)
4831
{
…
4842
}
4843
4844
/* Parameters are
handled by store_parm_decls, not cp_finish_decl.
*/
4845
my_friendly_assert (TREE_CODE (decl) !=
PARM_DECL, 19990828);
4846
4847
/* Take care of
TYPE_DECLs up front.
*/
4848
if (TREE_CODE (decl) == TYPE_DECL)
4849
{
…
4868
}
4869
4870
if (TREE_CODE (decl) != FUNCTION_DECL)
4871
ttype = target_type (type);
4872
4873
4874
/* Currently, GNU
C++ puts constants in text space, making them
4875
impossible to initialize. In
the future, one would hope for
4876
an operating system which
understood the difference between
4877
initialization and the running
of a program.
*/
4878
if (! DECL_EXTERNAL (decl) &&
TREE_READONLY (decl))
4879
{
4880
was_readonly = 1;
4881
if (TYPE_NEEDS_CONSTRUCTING (type)
4882
||
TREE_CODE (type) == REFERENCE_TYPE)
4883
TREE_READONLY (decl) = 0;
4884
}
4885
4886
if (TREE_CODE (decl) == VAR_DECL)
4887
{
4888
/* Only PODs can
have thread-local storage. Other types may require
4889
various kinds of non-trivial
initialization.
*/
4890
if (DECL_THREAD_LOCAL (decl) &&
!pod_type_p (TREE_TYPE (decl)))
4891
error ("`%D' cannot be thread-local
because it has non-POD type `%T'",
4892
decl, TREE_TYPE (decl));
4893
/* Convert the
initializer to the type of DECL, if we have not
4894
already initialized DECL.
*/
4895
if (!DECL_INITIALIZED_P (decl)
4896
/* If !DECL_EXTERNAL then DECL is being defined. In the
4897
case of a static data member initialized
inside the
4898
class-specifier, there can be an initializer
even if DECL
4899
is *not* defined.
*/
4900
&& (!DECL_EXTERNAL (decl) || init))
4901
{
4902
init = check_initializer
(decl, init, flags, &cleanup);
4903
/* Thread-local
storage cannot be dynamically initialized.
*/
4904
if
(DECL_THREAD_LOCAL (decl) && init)
4905
{
4906
error ("`%D' is thread-local and so
cannot be dynamically "
4907
"initialized", decl);
4908
init = NULL_TREE;
4909
}
4910
if
(DECL_EXTERNAL (decl) && init)
4911
{
4912
/* The static data member cannot be initialized by a
4913
non-constant when being declared.
*/
4914
error ("`%D' cannot be initialized
by a non-constant expression"
4915
" when being declared", decl);
4916
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
4917
init = NULL_TREE;
4918
}
4919
4920
/* Handle:
4921
4922
[dcl.init]
4923
4924
The memory occupied by any object of static
storage
4925
duration is zero-initialized at program
startup before
4926
any other initialization takes place.
4927
4928
We cannot create an appropriate
initializer until after
4929
the type of DECL is finalized. If
DECL_INITIAL is set,
4930
then the DECL is statically initialized,
and any
4931
necessary zero-initialization has already
been performed.
*/
4932
if
(TREE_STATIC (decl) && !DECL_INITIAL (decl))
4933
DECL_INITIAL (decl) = build_zero_init
(TREE_TYPE (decl),
4934
/*nelts=*/
NULL_TREE,
4935
/*static_storage_p=*/
true);
4936
/* Remember that the
initialization for this variable has
4937
taken place.
*/
4938
DECL_INITIALIZED_P (decl) = 1;
4939
/* This declaration is the definition of this variable,
4940
unless we are initializing a static data
member within
4941
the class specifier.
*/
4942
if
(!DECL_EXTERNAL (decl))
4943
var_definition_p = true;
4944
}
…
4951
}
Before entering the function, we clean DELC_CONTEXT of decl
. At
line 4794, maybe_apply_renaming_pragma
is only useful for Solaris and Tru64 UNIX system for compatibility with the
system headers.
returns to
the invocation of handling class C. This time build_vbase_offset_vtbl_entries
does nothing, as base A has been processed with BINFO_VTABLE_PATH_MARKED set. And
in build_vcall_offset_vtbl_entries
,
vid->generate_vcall_entries
is set in false for class C, and vid->vbase
is set to binfo of C. Below call
stack would be involved.
build_vcall_and_vbase_vtbl_entries:
for C
build_vcall_offset_vtbl_entries:
for C
add_vcall_offset_vtbl_entries_r:
for C
add_vcall_offset_vtbl_entries_r:
for B1
add_vcall_offset_vtbl_entries_r:
for A
add_vcall_offset_vtbl_entries_1:
for B1
add_vcall_offset:
for B1
add_vcall_offset_vtbl_entries_1:
for C
add_vcall_offset:
for C
add_vcall_offset_vtbl_entries_r:
for B2
add_vcall_offset_vtbl_entries_r:
for A
add_vcall_offset_vtbl_entries_1:
for B2
add_vcall_offset:
for B2
In above call
stack, add_vcall_offset_vtbl_entries_r
first recurses for C’s A, but it does nothing as condition at line 7680
satisified. In following add_vcall_offset
, vid->fns now holds
virtual functions seen above, so same_signature_p
at
line 7805 returns true for B1’s
virtual, and exits the function at line 7810. After returning from add_vcall_offset_vtbl_entries_r
handling B1, invoking add_vcall_offset_vtbl_entries_1
for C.
Similiarly, same_signature_p
returns true for C’s virtual. Then add_vcall_offset_vtbl_entries_r
at line 7698
is recursed for B2 (the non-primary base), it’s original primary base A is
filtered out by conidtion at line 7680, also in add_vcall_offset
, same_signature_p
returns true for B2’s virtual.
When exitting
from build_vcall_and_vbase_vtbl_entries
for C, we will get following vtable initializers and CLASSTYPE_VCALL_INDICES.
In above figure, in the
chain of CLASSTYPE_VCALL_INDICES, value
field of node A::f is -3; it coordinate
with A::f given in chain of last_init.
Back build_vtbl_initializer
, it is still handling
C.
build_vtbl_initializer (continue)
7378
/* If the target
requires padding between data entries, add that now.
*/
7379
if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
7380
{
…
7395
}
7396
7397
if (non_fn_entries_p)
7398
*non_fn_entries_p = list_length
(vid.inits);
7399
7400
/* Go through all
the ordinary virtual functions, building up
7401
initializers.
*/
7402
vfun_inits = NULL_TREE;
7403
for
(v =
BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
7404
{
7405
tree delta;
7406
tree vcall_index;
7407
tree fn, fn_original;
7408
tree init = NULL_TREE;
7409
7410
fn = BV_FN (v);
7411
fn_original = fn;
7412
if (DECL_THUNK_P (fn))
7413
{
7414
if (!DECL_NAME (fn))
7415
finish_thunk
(fn);
7416
if (THUNK_ALIAS (fn))
7417
{
7418
fn = THUNK_ALIAS (fn);
7419
BV_FN (v) = fn;
7420
}
7421
fn_original = THUNK_TARGET (fn);
7422
}
7423
7424
/* If the only
definition of this function signature along our
7425
primary base chain is from a
lost primary, this vtable slot will
7426
never be used, so just zero
it out. This is important to avoid
7427
requiring extra thunks which
cannot be generated with the function.
7428
7429
We first check this in
update_vtable_entry_for_fn, so we handle
7430
restored primary bases
properly; we also need to do it here so we
7431
zero out unused slots in
ctor vtables, rather than filling themff
7432
with erroneous values
(though harmless, apart from relocation
7433
costs).
*/
7434
for
(b = binfo;
; b = get_primary_binfo
(b))
7435
{
7436
/* We found a
defn before a lost primary; go ahead as normal.
*/
7437
if (look_for_overrides_here
(BINFO_TYPE (b), fn_original))
7438
break
;
7439
7440
/* The nearest
definition is from a lost primary; clear the
7441
slot.
*/
7442
if (BINFO_LOST_PRIMARY_P (b))
7443
{
7444
init = size_zero_node;
7445
break
;
7446
}
7447
}
7448
7449
if (! init)
7450
{
7451
/* Pull the
offset for `this', and the function to call, out of
7452
the list.
*/
7453
delta = BV_DELTA (v);
7454
vcall_index
= BV_VCALL_INDEX (v);
7455
7456
my_friendly_assert (TREE_CODE (delta) ==
INTEGER_CST, 19990727);
7457
my_friendly_assert (TREE_CODE (fn) ==
FUNCTION_DECL, 19990727);
7458
7459
/* You can't
call an abstract virtual function; it's abstract.
7460
So, we replace these functions
with __pure_virtual.
*/
7461
if (DECL_PURE_VIRTUAL_P (fn_original))
7462
fn = abort_fndecl;
7463
else if (!integer_zerop
(delta) || vcall_index)
7464
{
7465
fn = make_thunk
(fn, /*this_adjusting=*/
1, delta,
vcall_index);
7466
if (!DECL_NAME (fn))
7467
finish_thunk
(fn);
7468
}
7469
/* Take the
address of the function, considering it to be of an
7470
appropriate generic
type.
*/
7471
init = build1
(ADDR_EXPR, vfunc_ptr_type_node
,
fn);
7472
/* The address
of a function can't change.
*/
7473
TREE_CONSTANT (init) = 1;
7474
}
7475
7476
/* And add it to
the chain of initializers.
*/
7477
if (TARGET_VTABLE_USES_DESCRIPTORS)
7478
{
…
7493
}
7494
else
7495
vfun_inits = tree_cons (NULL_TREE, init,
vfun_inits);
7496
}
7497
7498
/* The initializers
for virtual functions were built up in reverse
7499
order; straighten them out
now.
*/
7450
vfun_inits = nreverse (vfun_inits);
7451
7452
/* The negative
offset initializers are also in reverse order.
*/
7453
vid.inits = nreverse (vid.inits);
7454
7455
/* Chain the two
together.
*/
7456
return
chainon (vid.inits, vfun_inits);
7457
}
Above orig_binfo
comes from current class, whose BINFO_VIRTUALS has been process by update_vtable_entry_for_fn
(see previous section). Virtuals in BINFO_VIRTUALS can be a thunk, which is
constructed in update_vtable_entry_for_fn
, and only of result-adjustmnet.
Here it is constructing this-adjustment thunk, and information BV_DELTA, BV_VCALL_INDEX
(from CLASSTYPE_VCALL_INDICES of the virtual base. Above can see C also
prepared it for future being virtual base) is also collected by update_vtable_entry_for_fn
.
Now all thunks are still anonymous. In the front-end, that indicates
the thunk is incomplete.
194
void
195
finish_thunk
(tree thunk)
in
method.c
196
{
197
tree function, name;
198
tree fixed_offset = ssize_int
(THUNK_FIXED_OFFSET (thunk));
199
tree virtual_offset = THUNK_VIRTUAL_OFFSET
(thunk);
200
201
my_friendly_assert (!DECL_NAME (thunk)
&& DECL_THUNK_P (thunk), 20021127);
202
if (virtual_offset &&
DECL_RESULT_THUNK_P (thunk))
203
virtual_offset = BINFO_VPTR_FIELD
(virtual_offset);
204
function = THUNK_TARGET (thunk);
205
name = mangle_thunk (function,
DECL_THIS_THUNK_P (thunk),
206
fixed_offset, virtual_offset);
207
208
/* We can end up
with declarations of (logically) different
209
covariant thunks,
that do identical adjustments. The two thunks
210
will be adjusting
between within different hierarchies, which
211
happen to have
the same layout. We must nullify one of them to
212
refer to the
other.
*/
213
if (DECL_RESULT_THUNK_P (thunk))
214
{
215
tree cov_probe;
216
217
for
(cov_probe = DECL_THUNKS (function);
218
cov_probe; cov_probe = TREE_CHAIN
(cov_probe))
219
if (DECL_NAME (cov_probe) == name)
220
{
221
my_friendly_assert (!DECL_THUNKS (thunk),
20031023);
222
THUNK_ALIAS (thunk) = (THUNK_ALIAS
(cov_probe)
223
? THUNK_ALIAS (cov_probe) : cov_probe);
224
break
;
225
}
226
}
227
228
DECL_NAME (thunk) = name;
229
SET_DECL_ASSEMBLER_NAME (thunk, name);
230
}
THUNK_VIRTUAL_OFFSET, for this-adjusting thunk, it is the number of
bytes to be added to the vtable to find the vcall offset; for a result
adjusting thunk, it is the binfo of the relevant virtual base. BINFO_VPTR_FIELD
at line 203 is an INTEGER_CST giving an offset into the vtable where the offset
to the virtual base can be found. So for result adjusting thunk, needs
treatment at line 203 to get the offset of the virtual base. At line 205, mangle_thunk
returns the mangled name for the thunk (at section beginning, we have seen
examples of thunk’s mangled name). After setting the name with the thunk, it
can be regarded as finished. As thunk’s name is constructed by its action, it’s
possible there exists thunk of same name, at which treats the thunk built later
as the alias of the former one, they share the same thunk function.
dfs_accumulate_vtbl_inits
(continue)
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
}
Back to dfs_accumulate_vtbl_inits
, note that we are
still handling class C. above l
is list
in finish_vtbls
, in its TREE_PURPOSE is the TYPE_BINFO_VTABLE
(vtable saved in the binfo of the type, which is VAR_DECL generated by build_primary_vtable
).
And originally, TREE_VALUE of l
is NULL (but at line 7185 in accumulate_vtbl_inits
, it chains l
with
the list returned by dfs_accumulate_vtbl_inits
). See that non_fn_entries
records the number of entries of negative index. So it can know where to begin
the entries visible to programmer.
When returns back to accumulate_vtbl_inits
, after chaining into list
in finish_vtt
,
we get following figure (remember in create_vtable_ptr
, every virtual function has
an extra node generated with 0 delta).
Next, in accumulate_vtbl_inits
,
at line 7195, in FOR
block, binfo B1
within C is not handled as its BINFO_NEW_VTABLE_MARKED unset (see dfs_accumulate_vtbl_inits
line 7273). While for B2 in
C, it has secondary vtable generated, so passes the line successfully. At that
time, ctor_vtbl_p
is false, binfo
from class B2, orig_binfo
from B2 in C, and rtti_binfo
is C’s binfo, it undergoes similar processing as that for C above. Then when
back finish_vtbls
,
A in C is processed by accumulate_vtbl_inits
at
line 6780, in which ctor_vtbl_p
is still false. But this A hasn’t
flag BINFO_NEW_VTABLE_MARKED set, so exits dfs_accumulate_vtbl_inits
immediately.
So before
invoking initialize_vtable
at line 6784, list
is given in below figure.
(Click
here for open
)
Figure 117
: initializer for vtable
Above B1 and A don’t have their part of vtable as they share the
same part with C.
In below function, now argument inits
is the chain referred by value slot of list
in
above figure. This chain holds all initializers for class C’s vtable. Note that
at last vtbl
at line 7297 in dfs_accumulate_vtbl_inits
,
points to the start point of vtable of specified class which is a PLUS_EXPR of
vtbl+4 for C, vtbl+8 for base B2.
6789
static
void
6790
initialize_vtable
(tree binfo, tree
inits)
in
class.c
6791
{
6792
tree decl;
6793
6794
layout_vtable_decl
(binfo, list_length (inits));
6795
decl = get_vtbl_decl_for_binfo
(binfo);
6796
initialize_array
(decl, inits);
6797
dump_vtable (BINFO_TYPE (binfo), binfo, decl);
6798
}
Originally in build_vtable
, vtable is created as type of vtbl_type_node
which is the array of type vtable_entry_type
with empty dimension. Now the
size of the array is settled down, we can create the exact type by layout_vtable_decl
.
1778
static
void
1779
layout_vtable_decl
(tree binfo, int n)
in
class.c
1780
{
1781
tree atype;
1782
tree vtable;
1783
1784
atype = build_cplus_array_type (vtable_entry_type
,
1785
build_index_type
(size_int (n - 1)));
1786
layout_type
(atype);
1787
1788
/* We may have to
grow the vtable.
*/
1789
vtable = get_vtbl_decl_for_binfo
(binfo);
1790
if (!same_type_p (TREE_TYPE (vtable), atype))
1791
{
1792
TREE_TYPE (vtable) = atype;
1793
DECL_SIZE (vtable) = DECL_SIZE_UNIT
(vtable) = NULL_TREE;
1794
layout_decl
(vtable, 0);
1795
}
1796
}
So at line 6795, the vtable VAR_DECL fetched has correct type
defined. And it is passed as argument decl
in below function.
6803
static
void
6804
initialize_array
(tree decl, tree inits)
in
class.c
6805
{
6806
tree context;
6807
6808
context = DECL_CONTEXT (decl);
6809
DECL_CONTEXT (decl) = NULL_TREE;
6810
DECL_INITIAL (decl) = build_constructor
(NULL_TREE, inits);
6811
TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) =
1;
6812
cp_finish_decl
(decl, DECL_INITIAL (decl), NULL_TREE, 0);
6813
DECL_CONTEXT (decl) = context;
6814
}
See node of CONSTRUCTOR is built for initializing this VAR_DECL.
Note that this node has empty type
field (it is treated as unknown).
444
tree
445
build_constructor
(tree type, tree vals)
in
tree.c
446
{
447
tree c = make_node
(CONSTRUCTOR);
448
TREE_TYPE (c) = type;
449
CONSTRUCTOR_ELTS (c) = vals;
450
451
/* ??? May not be
necessary. Mirrors what build does.
*/
452
if (vals)
453
{
454
TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS
(vals);
455
TREE_READONLY (c) = TREE_READONLY (vals);
456
TREE_CONSTANT (c) = TREE_CONSTANT (vals);
457
}
458
else
459
TREE_CONSTANT (c) = 0;
/* safe side */
460
461
return
c;
462
}
Being a VAR_DECL, it is completed by cp_finish_decl
. Note that we
are still within another cp_finish_decl
for the template instantiation
of SmallObject.
4768
void
4769
cp_finish_decl
(tree decl, tree init,
tree asmspec_tree, int flags)
in decl.c
4770
{
4771
tree type;
4772
tree ttype = NULL_TREE;
4773
tree cleanup;
4774
const
char
*asmspec = NULL;
4775
int was_readonly = 0;
4776
bool var_definition_p = false;
4777
4778
if (decl == error_mark_node)
4779
return
;
4780
else if (! decl)
4781
{
4782
if (init)
4783
error ("assignment (not
initialization) in declaration");
4784
return
;
4785
}
4786
4787
my_friendly_assert (TREE_CODE (decl) !=
RESULT_DECL, 20030619);
4788
4789
/* Assume no
cleanup is required.
*/
4790
cleanup = NULL_TREE;
4791
4792
/* If a name was
specified, get the string.
*/
4793
if (global_scope_p (current_binding_level
))
4794
asmspec_tree = maybe_apply_renaming_pragma
(decl, asmspec_tree);
4795
if (asmspec_tree)
4796
asmspec = TREE_STRING_POINTER
(asmspec_tree);
4797
4798
if (init && TREE_CODE (init) ==
NAMESPACE_DECL)
4799
{
4800
error ("cannot initialize `%D' to
namespace `%D'",
4802
decl, init);
4803
init = NULL_TREE;
4804
}
4805
4806
if (current_class_type
4807
&& CP_DECL_CONTEXT (decl) == current_class_type
4808
&& TYPE_BEING_DEFINED (current_class_type
)
4809
&& (DECL_INITIAL (decl) || init))
4810
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
4811
4812
if (TREE_CODE (decl) == VAR_DECL
4813
&& DECL_CONTEXT (decl)
4814
&& TREE_CODE (DECL_CONTEXT (decl))
== NAMESPACE_DECL
4815
&& DECL_CONTEXT (decl) != current_namespace
4816
&& init)
4817
{
4818
/* Leave the namespace of the object.
*/
4819
pop_decl_namespace ();
4820
}
4821
4822
type = TREE_TYPE (decl);
4823
4824
if (type == error_mark_node)
4825
goto
finish_end0;
4826
4827
if (TYPE_HAS_MUTABLE_P (type))
4828
TREE_READONLY (decl) = 0;
4829
4830
if (processing_template_decl
)
4831
{
…
4842
}
4843
4844
/* Parameters are
handled by store_parm_decls, not cp_finish_decl.
*/
4845
my_friendly_assert (TREE_CODE (decl) !=
PARM_DECL, 19990828);
4846
4847
/* Take care of
TYPE_DECLs up front.
*/
4848
if (TREE_CODE (decl) == TYPE_DECL)
4849
{
…
4868
}
4869
4870
if (TREE_CODE (decl) != FUNCTION_DECL)
4871
ttype = target_type (type);
4872
4873
4874
/* Currently, GNU
C++ puts constants in text space, making them
4875
impossible to initialize. In
the future, one would hope for
4876
an operating system which
understood the difference between
4877
initialization and the running
of a program.
*/
4878
if (! DECL_EXTERNAL (decl) &&
TREE_READONLY (decl))
4879
{
4880
was_readonly = 1;
4881
if (TYPE_NEEDS_CONSTRUCTING (type)
4882
||
TREE_CODE (type) == REFERENCE_TYPE)
4883
TREE_READONLY (decl) = 0;
4884
}
4885
4886
if (TREE_CODE (decl) == VAR_DECL)
4887
{
4888
/* Only PODs can
have thread-local storage. Other types may require
4889
various kinds of non-trivial
initialization.
*/
4890
if (DECL_THREAD_LOCAL (decl) &&
!pod_type_p (TREE_TYPE (decl)))
4891
error ("`%D' cannot be thread-local
because it has non-POD type `%T'",
4892
decl, TREE_TYPE (decl));
4893
/* Convert the
initializer to the type of DECL, if we have not
4894
already initialized DECL.
*/
4895
if (!DECL_INITIALIZED_P (decl)
4896
/* If !DECL_EXTERNAL then DECL is being defined. In the
4897
case of a static data member initialized
inside the
4898
class-specifier, there can be an initializer
even if DECL
4899
is *not* defined.
*/
4900
&& (!DECL_EXTERNAL (decl) || init))
4901
{
4902
init = check_initializer
(decl, init, flags, &cleanup);
4903
/* Thread-local
storage cannot be dynamically initialized.
*/
4904
if
(DECL_THREAD_LOCAL (decl) && init)
4905
{
4906
error ("`%D' is thread-local and so
cannot be dynamically "
4907
"initialized", decl);
4908
init = NULL_TREE;
4909
}
4910
if
(DECL_EXTERNAL (decl) && init)
4911
{
4912
/* The static data member cannot be initialized by a
4913
non-constant when being declared.
*/
4914
error ("`%D' cannot be initialized
by a non-constant expression"
4915
" when being declared", decl);
4916
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
4917
init = NULL_TREE;
4918
}
4919
4920
/* Handle:
4921
4922
[dcl.init]
4923
4924
The memory occupied by any object of static
storage
4925
duration is zero-initialized at program
startup before
4926
any other initialization takes place.
4927
4928
We cannot create an appropriate
initializer until after
4929
the type of DECL is finalized. If
DECL_INITIAL is set,
4930
then the DECL is statically initialized,
and any
4931
necessary zero-initialization has already
been performed.
*/
4932
if
(TREE_STATIC (decl) && !DECL_INITIAL (decl))
4933
DECL_INITIAL (decl) = build_zero_init
(TREE_TYPE (decl),
4934
/*nelts=*/
NULL_TREE,
4935
/*static_storage_p=*/
true);
4936
/* Remember that the
initialization for this variable has
4937
taken place.
*/
4938
DECL_INITIALIZED_P (decl) = 1;
4939
/* This declaration is the definition of this variable,
4940
unless we are initializing a static data
member within
4941
the class specifier.
*/
4942
if
(!DECL_EXTERNAL (decl))
4943
var_definition_p = true;
4944
}
…
4951
}
Before entering the function, we clean DELC_CONTEXT of decl
. At
line 4794, maybe_apply_renaming_pragma
is only useful for Solaris and Tru64 UNIX system for compatibility with the
system headers.
相关文章推荐
- Studying note of GCC-3.4.6 source (141 - cont 2)
- Studying note of GCC-3.4.6 source (139 - cont 2)
- Studying note of GCC-3.4.6 source (24 cont)
- Studying note of GCC-3.4.6 source (147 - cont 1)
- Studying note of GCC-3.4.6 source (147 - cont 2)
- Studying note of GCC-3.4.6 source (141)
- Studying note of GCC-3.4.6 source (19 cont)
- Studying note of GCC-3.4.6 source (139 - cont 1)
- Studying note of GCC-3.4.6 source (25 cont1)
- Studying note of GCC-3.4.6 source (68)
- Studying note of GCC-3.4.6 source (87)
- Studying note of GCC-3.4.6 source (103)
- Studying note of GCC-3.4.6 source (104)
- Studying note of GCC-3.4.6 source (121)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (146)
- Studying note of GCC-3.4.6 source (22)
- Studying note of GCC-3.4.6 source (25 cont2)