然后 调用 check_initializer 来验证初始值。在这里 参数 flags 是 0 。
4463 static tree
4464 check_initializer (tree decl, tree init, int flags, tree *cleanup) in decl.c
4465 {
4466 tree type = TREE_TYPE (decl);
4467 tree init_code = NULL;
4468
4469 /* If `start_decl' didn't like having an initialization, ignore it now. */
4470 if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
4471 init = NULL_TREE;
4472
4473 /* If an initializer is present, DECL_INITIAL has been
4474 error_mark_node, to indicate that an as-of-yet unevaluated
4475 initialization will occur. From now on, DECL_INITIAL reflects
4476 the static initialization -- if any -- of DECL. */
4477 DECL_INITIAL (decl) = NULL_TREE;
4478
4479 /* Things that are going to be initialized need to have complete
4480 type. */
4481 TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
4482
4483 if (type == error_mark_node)
4484 /* We will have already complained. */
4485 init = NULL_TREE;
4486 else if (init && COMPLETE_TYPE_P (type)
4487 && !TREE_CONSTANT (TYPE_SIZE (type)))
4488 {
4489 error ("variable-sized object `%D' may not be initialized", decl);
4490 init = NULL_TREE;
4491 }
4492 else if (TREE_CODE (type) == ARRAY_TYPE
4493 && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
4494 {
4495 error ("elements of array `%#D' have incomplete type", decl);
4496 init = NULL_TREE;
4497 }
4498 else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
4499 {
4500 error ("`%D' has incomplete type", decl);
4501 TREE_TYPE (decl) = error_mark_node;
4502 init = NULL_TREE;
4503 }
4504
4505 if (TREE_CODE (decl) == CONST_DECL)
4506 {
4507 my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
4508
4509 DECL_INITIAL (decl) = init;
4510
4511 my_friendly_assert (init != NULL_TREE, 149);
4512 init = NULL_TREE;
4513 }
4514 else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
4515 init = grok_reference_init (decl, type, init, cleanup);
4516 else if (init)
4517 {
4518 if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
4519 {
4520 /* [dcl.init] paragraph 13,
4521 If T is a scalar type, then a declaration of the form
4522 T x = { a };
4523 is equivalent to
4524 T x = a;
4525
4526 reshape_init will complain about the extra braces,
4527 and doesn't do anything useful in the case where TYPE is
4528 scalar, so just don't call it. */
4529 if (CP_AGGREGATE_TYPE_P (type))
4530 init = reshape_init (type, &init);
4531
4532 if ((*targetm .vector_opaque_p) (type))
4533 {
4534 error ("opaque vector types cannot be initialized");
4535 init = error_mark_node;
4536 }
4537 }
C++ 标准的某一条款( [dcl.init.aggr] )澄清到:
当使用一个初始化值列表中的初始值初始化聚合成员(注:聚合指关键字 class , struct , union 声明的类型,以及数组)时,考虑所有隐式类型转换( implicit type conversions )(条文 4 )。如果该初始值能初始化一个成员,该成员就是初始化了的。否则,如果该成员本身是一个非空的子聚合,假定省略括号,该初始值用作该子聚合的第一个成员的初始化。例如:
struct A {
int i;
operator int();
};
struct B {
A a1, a2;
int z;
};
A a;
B b = { 4, a, a };
用于 b.a1.i 初始值两边的大括号被省略。 b.a1.i 被 4 初始化, b.a2 被 a 初始化, b.z 被操作符 a.operator int() 的返回值初始化。
函数 reshape_init 被调用来把初始值列表从形式 {4, a, a } ,变换为 { {4, a}, a} ,后面的形式才是前端需要的。
这里对于我们的例子,该 VAR_DECL 是一个 vtable_entry_type 类型的数组,而 initp 指向用于初始值的 CONSTRUCTOR 节点,它是深思熟虑地被创建为空类型的。因此在 4289 行的代码块被执行。 CONSTRUCTOR_ELTS 返回上面构建的 inits 。这些初始值按被大括号所包围那样处理。
4267 static tree
4268 reshape_init (tree type, tree *initp) in decl.c
4269 {
4270 tree inits;
4271 tree old_init;
4272 tree old_init_value;
4273 tree new_init;
4274 bool brace_enclosed_p;
4275 bool string_init_p;
4276
4277 old_init = *initp;
4278 old_init_value = (TREE_CODE (*initp) == TREE_LIST
4279 ? TREE_VALUE (*initp) : old_init);
4280
4281 my_friendly_assert (old_init_value, 20030723);
4282
4283 /* If the initializer is brace-enclosed, pull initializers from the
4284 enclosed elements. Advance past the brace-enclosed initializer
4285 now. */
4286 if (TREE_CODE (old_init_value) == CONSTRUCTOR
4287 && TREE_TYPE (old_init_value) == NULL_TREE
4288 && TREE_HAS_CONSTRUCTOR (old_init_value))
4289 {
4290 *initp = TREE_CHAIN (old_init);
4291 TREE_CHAIN (old_init) = NULL_TREE;
4292 inits = CONSTRUCTOR_ELTS (old_init_value);
4293 initp = &inits;
4294 brace_enclosed_p = true;
4295 }
4296 else
4297 {
4298 inits = NULL_TREE;
4299 brace_enclosed_p = false;
4300 }
4301
4302 /* A non-aggregate type is always initialized with a single
4303 initializer. */
4304 if (!CP_AGGREGATE_TYPE_P (type))
4305 {
4306 *initp = TREE_CHAIN (old_init);
4307 TREE_CHAIN (old_init) = NULL_TREE;
4308 /* It is invalid to initialize a non-aggregate type with a
4309 brace-enclosed initializer. */
4310 if (brace_enclosed_p)
4311 {
4312 error ("brace-enclosed initializer used to initialize `%T'",
4313 type);
4314 if (TREE_CODE (old_init) == TREE_LIST)
4315 TREE_VALUE (old_init) = error_mark_node;
4316 else
4317 old_init = error_mark_node;
4318 }
4319
4320 return old_init;
4321 }
4322
4323 /* [dcl.init.aggr]
4324
4325 All implicit type conversions (clause _conv_) are considered when
4326 initializing the aggregate member with an initializer from an
4327 initializer-list. If the initializer can initialize a member,
4328 the member is initialized. Otherwise, if the member is itself a
4329 non-empty subaggregate, brace elision is assumed and the
4330 initializer is considered for the initialization of the first
4331 member of the subaggregate. */
4332 if (!brace_enclosed_p
4333 && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
4334 {
4335 *initp = TREE_CHAIN (old_init);
4336 TREE_CHAIN (old_init) = NULL_TREE;
4337 return old_init;
4338 }
4339
4340 string_init_p = false;
4341 if (TREE_CODE (old_init_value) == STRING_CST
4342 && TREE_CODE (type) == ARRAY_TYPE
4343 && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
4344 {
…
4356 }
4357 else
4358 {
4359 /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
4360 new_init = build_constructor (type, NULL_TREE);
4361 TREE_HAS_CONSTRUCTOR (new_init) = 1;
4362
4363 if (CLASS_TYPE_P (type))
4364 {
…
4419 }
4420 else if ((TREE_CODE (type) == ARRAY_TYPE)|| (TREE_CODE (type) == VECTOR_TYPE))
4421 {
4422 tree max_index;
4423
4424 /* If the bound of the array is known, take no more initializers
4425 than are allowed. */
4426 max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE))
4427 ? array_type_nelts (type) : NULL_TREE);
4428 if (!reshape_init_array (TREE_TYPE (type), max_index,
4429 initp, new_init))
4430 return error_mark_node;
4431 }
4432 else
4433 abort ();
4434
4435 /* The initializers were placed in reverse order in the
4436 CONSTRUCTOR. */
4437 CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
4438
4439 if (TREE_CODE (old_init) == TREE_LIST)
4440 new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
4441 }
4442
4443 /* If there are more initializers than necessary, issue a
4444 diagnostic. */
4445 if (*initp)
4446 {
4447 if (brace_enclosed_p)
4448 error ("too many initializers for `%T'", type);
4449 else if (warn_missing_braces && !string_init_p)
4450 warning ("missing braces around initializer");
4451 }
4452
4453 return new_init;
4454 }
看到对于聚合类型的成员, 4333 行确认初始值的类型能被转换到成员的类型。对于数组,下面的 reshape_init_array 遍历成员,使用 reshape_init 为每个成员验证及重塑初始值。而对于非聚合类型成员,初始值立即被返回。
4203 static bool
4204 reshape_init_array (tree elt_type, tree max_index, in decl.c
4205 tree *initp, tree new_init)
4206 {
4207 bool sized_array_p = (max_index != NULL_TREE);
4208 unsigned HOST_WIDE_INT max_index_cst = 0;
4209 unsigned HOST_WIDE_INT index;
4210
4211 if (sized_array_p)
4212 {
4213 if (host_integerp (max_index, 1))
4214 max_index_cst = tree_low_cst (max_index, 1);
4215 /* sizetype is sign extended, not zero extended. */
4216 else
4217 max_index_cst = tree_low_cst (convert (size_type_node, max_index), 1);
4218 }
4219
4220 /* Loop until there are no more initializers. */
4221 for (index = 0;
4222 *initp && (!sized_array_p || index <= max_index_cst);
4223 ++index)
4224 {
4225 tree element_init;
4226 tree designated_index;
4227
4228 element_init = reshape_init (elt_type, initp);
4229 if (element_init == error_mark_node)
4230 return false;
4231 TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
4232 CONSTRUCTOR_ELTS (new_init) = element_init;
4233 designated_index = TREE_PURPOSE (element_init);
4234 if (designated_index)
4235 {
4236 /* Handle array designated initializers (GNU extension). */
4237 if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
4238 {
4239 error ("name `%D' used in a GNU-style designated "
4240 "initializer for an array", designated_index);
4241 TREE_PURPOSE (element_init) = NULL_TREE;
4242 }
4243 else
4244 abort ();
4245 }
4246 }
4247
4248 return true;
4259 }
这里我们例子中每个初始值的 TREE_PURPOSE 都是空的( TREE_PURPOSE 用于所谓的指定初始化, IBM 的 XL C 支持这一特性,详情参见 这里 )。看到新产生的 CONSTRUCTOR ,与之前的相比,赋上了类型。
那么在 check_initializer 的 4532 行,在 x86 机器上, targetm 中的 vector_opaque_p 钩子总是返回 false 。而下面的 maybe_deduce_size_from_array_init 设置了数组节点的 size 域,例如:“ int a[] = { 1, 2, 3}; ”该函数应该在节点中设置大小 3 。
check_initializer (continue)
4539 /* If DECL has an array type without a specific bound, deduce the
4540 array size from the initializer. */
4541 maybe_deduce_size_from_array_init (decl, init);
4542 type = TREE_TYPE (decl);
4543 if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
4544 TREE_TYPE (init) = type;
4545
4546 if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
4547 {
…
4579 }
4580 else
4581 {
4582 dont_use_constructor:
4583 if (TREE_CODE (init) != TREE_VEC)
4584 {
4585 init_code = store_init_value (decl, init);
4586 init = NULL;
4587 }
4588 }
4589 }
4590 else if (DECL_EXTERNAL (decl))
4591 ;
4592 else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
4593 goto initialize_aggr;
4594 else if (IS_AGGR_TYPE (type))
4595 {
4596 tree core_type = strip_array_types (type);
4597
4598 if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
4599 error ("structure `%D' with uninitialized const members", decl);
4600 if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
4601 error ("structure `%D' with uninitialized reference members",
4602 decl);
4603
4604 check_for_uninitialized_const_var (decl);
4605 }
4606 else
4607 check_for_uninitialized_const_var (decl);
4608
4609 if (init && init != error_mark_node)
4610 init_code = build (INIT_EXPR, type, decl, init);
4611
4612 return init_code;
4613 }
decl 的类型是 vtbl_type_node ——元素类型为 vtable_entry_type 的 ARRAY_TYPE , vtable_entry_type 本身则是某个函数类型的指针;显然没有构造函数是为这个 ARRAY_TYPE 定义的。那么对于 type , 4546 行条件是 false 。
410 tree
411 store_init_value (tree decl, tree init) in typeck2.c
412 {
413 tree value, type;
414
415 /* If variable's type was invalidly declared, just ignore it. */
416
417 type = TREE_TYPE (decl);
418 if (TREE_CODE (type) == ERROR_MARK)
419 return NULL_TREE;
420
421 if (IS_AGGR_TYPE (type))
422 {
…
432 }
433 else if (TREE_CODE (init) == TREE_LIST
434 && TREE_TYPE (init) != unknown_type_node)
435 {
…
448 }
449
450 /* Digest the specified initializer into an expression. */
451 value = digest_init (type, init, (tree *) 0);
452 /* If the initializer is not a constant, fill in DECL_INITIAL with
453 the bits that are constant, and then return an expression that
454 will perform the dynamic initialization. */
455 if (value != error_mark_node
456 && (! TREE_CONSTANT (value)
457 || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
458 return split_nonconstant_init (decl, value);
459 /* If the value is a constant, just put it in DECL_INITIAL. If DECL
460 is an automatic variable, the middle end will turn this into a
461 dynamic initialization later. */
462 DECL_INITIAL (decl) = value;
463 return NULL_TREE;
464 }
这里的参数 type 是 VAR_DECL 的类型。初始值的类型不需要与对应的成员一致,只要能找到合适的转换函数。 digest_init 的目的就是,如果 type 及 init 不能完全匹配,找出合用的转换函数,并为这个转换操作产生必要的代码。
476 tree
477 digest_init (tree type, tree init, tree* tail) in typeck2.c
478 {
479 enum tree_code code = TREE_CODE (type);
480 tree element = NULL_TREE;
481 tree old_tail_contents = NULL_TREE;
482 /* Nonzero if INIT is a braced grouping. */
483 int raw_constructor;
484
485 /* By default, assume we use one element from a list.
486 We correct this later in the sole case where it is not true. */
487
488 if (tail)
489 {
490 old_tail_contents = *tail;
491 *tail = TREE_CHAIN (*tail);
492 }
493
494 if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST
495 && TREE_VALUE (init) == error_mark_node))
496 return error_mark_node;
497
498 if (TREE_CODE (init) == ERROR_MARK)
499 /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
500 a template function. This gets substituted during instantiation. */
501 return init;
502
503 /* We must strip the outermost array type when completing the type,
504 because the its bounds might be incomplete at the moment. */
505 if (!complete_type_or_else (TREE_CODE (type) == ARRAY_TYPE
506 ? TREE_TYPE (type) : type, NULL_TREE))
507 return error_mark_node;
508
509 /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
510 if (TREE_CODE (init) == NON_LVALUE_EXPR)
511 init = TREE_OPERAND (init, 0);
512
513 raw_constructor = (TREE_CODE (init) == CONSTRUCTOR
514 && TREE_HAS_CONSTRUCTOR (init));
515
516 if (raw_constructor
517 && CONSTRUCTOR_ELTS (init) != 0
518 && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)
519 {
520 element = TREE_VALUE (CONSTRUCTOR_ELTS (init));
521 /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
522 if (element && TREE_CODE (element) == NON_LVALUE_EXPR)
523 element = TREE_OPERAND (element, 0);
524 if (element == error_mark_node)
525 return element;
526 }
527
528 /* Initialization of an array of chars from a string constant
529 optionally enclosed in braces. */
530
531 if (code == ARRAY_TYPE)
532 {
533 tree typ1;
534
535 if (TREE_CODE (init) == TREE_LIST)
536 {
537 error ("initializing array with parameter list");
538 return error_mark_node;
539 }
540
541 typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
542 if (char_type_p (typ1)
543 && ((init && TREE_CODE (init) == STRING_CST)
544 || (element && TREE_CODE (element) == STRING_CST)))
545 {
…
577 }
578 }
579
580 /* Handle scalar types, including conversions,
581 and signature pointers and references. */
582
583 if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
584 || code == ENUMERAL_TYPE || code == REFERENCE_TYPE
585 || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
586 || TYPE_PTR_TO_MEMBER_P (type))
587 {
588 if (raw_constructor)
589 {
590 if (element == 0)
591 {
592 error ("initializer for scalar variable requires one element");
593 return error_mark_node;
594 }
595 init = element;
596 }
597 while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
598 {
599 pedwarn ("braces around scalar initializer for `%T'", type);
600 init = CONSTRUCTOR_ELTS (init);
601 if (TREE_CHAIN (init))
602 pedwarn ("ignoring extra initializers for `%T'", type);
603 init = TREE_VALUE (init);
604 }
605
606 return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
607 "initialization", NULL_TREE, 0);
608 }
609
610 /* Come here only for records and arrays (and unions with constructors). */
611
612 if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
613 {
614 error ("variable-sized object of type `%T' may not be initialized",
615 type);
616 return error_mark_node;
617 }
618
619 if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code))
620 {
621 if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)
622 && TREE_HAS_CONSTRUCTOR (init))
623 {
624 error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
625 type, init);
626 return error_mark_node;
627 }
628 else if (raw_constructor)
629 return process_init_constructor (type, init, (tree *)0);
…
649 }
650
651 error ("invalid initializer");
652 return error_mark_node;
653 }
对于我们例子的初始值,在 513 行, raw_constructor 为非 0 值;而 code 是 ARRAY_TYPE 。那么参数 init 被传递入 process_init_constructor 进行处理。
670 static tree
671 process_init_constructor (tree type, tree init, tree* elts) in typeck2.c
672 {
673 tree tail;
674 /* List of the elements of the result constructor,
675 i n reverse order. */
676 tree members = NULL;
677 tree next1;
678 tree result;
679 int allconstant = 1;
680 int allsimple = 1;
681 int erroneous = 0;
682
683 /* Make TAIL be the list of elements to use for the initialization,
684 no matter how the data was given to us. */
685
686 if (elts)
687 {
688 if (warn_missing_braces )
689 warning ("aggregate has a partly bracketed initializer");
690 tail = *elts;
691 }
692 else
693 tail = CONSTRUCTOR_ELTS (init);
694
695 /* Gobble as many elements as needed, and make a constructor or initial value
696 for each element of this aggregate. Chain them together in result.
697 If there are too few, use 0 for each scalar ultimate component. */
698
699 if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
700 {
701 long len;
702 int i;
703
704 if (TREE_CODE (type) == ARRAY_TYPE)
705 {
706 tree domain = TYPE_DOMAIN (type);
707 if (domain)
708 len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))
709 - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))
710 + 1);
711 else
712 len = -1; /* Take as many as there are. */
713 }
714 else
715 {
716 /* Vectors are like simple fixed-size arrays. */
717 len = TYPE_VECTOR_SUBPARTS (type);
718 }
719
720 for (i = 0; len < 0 || i < len; i++)
721 {
722 if (tail)
723 {
724 if (TREE_PURPOSE (tail)
725 && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
726 || compare_tree_int (TREE_PURPOSE (tail), i) != 0))
727 sorry ("non-trivial labeled initializers");
728
729 if (TREE_VALUE (tail) != 0)
730 {
731 tree tail1 = tail;
732 next1 = digest_init (TREE_TYPE (type),
733 TREE_VALUE (tail), &tail1);
734 if (next1 == error_mark_node)
735 return next1;
736 my_friendly_assert
737 (same_type_ignoring_top_level_qualifiers_p
738 (TREE_TYPE (type), TREE_TYPE (next1)),
739 981123);
740 my_friendly_assert (tail1 == 0
741 || TREE_CODE (tail1) == TREE_LIST, 319);
742 if (tail == tail1 && len < 0)
743 {
744 error ("non-empty initializer for array of empty elements");
745 /* Just ignore what we were supposed to use. */
746 tail1 = NULL_TREE;
747 }
748 tail = tail1;
749 }
750 else
751 {
752 next1 = error_mark_node;
753 tail = TREE_CHAIN (tail);
754 }
755 }
756 else if (len < 0)
757 /* We're done. */
758 break ;
759 else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
760 {
…
771 }
772 else if (! zero_init_p (TREE_TYPE (type)))
773 next1 = build_zero_init (TREE_TYPE (type),
774 /*nelts=*/ NULL_TREE,
775 /*static_storage_p=*/ false);
776 else
777 /* The default zero-initialization is fine for us; don't
778 add anything to the CONSTRUCTOR. */
779 break ;
780
781 if (next1 == error_mark_node)
782 erroneous = 1;
783 else if (!TREE_CONSTANT (next1))
784 allconstant = 0;
785 else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
786 allsimple = 0;
787 members = tree_cons (size_int (i), next1, members);
788 }
789 }
790 else if (TREE_CODE (type) == RECORD_TYPE)
791 {
…
908 }
909 else if (TREE_CODE (type) == UNION_TYPE
910 /* If the initializer was empty, use default zero initialization. */
911 && tail)
912 {
…
977 }
978
979 /* If arguments were specified as a list, just remove the ones we used. */
980 if (elts)
981 *elts = tail;
982 /* If arguments were specified as a constructor,
983 complain unless we used all the elements of the constructor. */
984 else if (tail)
985 pedwarn ("excess elements in aggregate initializer");
986
987 if (erroneous)
988 return error_mark_node;
989
990 result = build_constructor (type, nreverse (members));
991 if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE)
992 complete_array_type (type, result, /*do_default=*/ 0);
993 if (init)
994 TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
995 if (allconstant) TREE_CONSTANT (result) = 1;
996 if (allconstant && allsimple) TREE_STATIC (result) = 1;
997 return result;
998 }
毫不奇怪,对于 ARRAY_TYPE 的每个元素,递归调用了 digest_init 。注意在对 digest_init 的递归调用中,参数 tail 不为空,它就是初始值。在 digest_init 中如果能成功处理初始值的一部分,该部分初始值即从列表中移除。在 606 行, convert_for_initialization 被调用来做可能需要的转换。这里在我们的例子中,不需要转换因为我们事先把 init 的类型设为 vtable_entry_type 。结果,该函数直接把 init 返回。
从 convert_for_initialization 返回同时直接退出 digest_init ,这意味着该(部分)初始值匹配已经成功。看到在 787 行,这个返回值被链入 members 。接着在 990 行,构建了一个新的 CONSTRUCTOR 。显然 vtable 的所有成员都是常量。而且这个 CONSTRUCTOR 将分配静态存储空间(即初始化静态成员)。接着这个在 cp_finish_decl 的 4902 行, store_init_value 返回了 NULL 。
cp_finish_decl (continue)
4953 /* Add this declaration to the statement-tree. This needs to happen
4954 after the call to check_initializer so that the DECL_STMT for a
4955 reference temp is added before the DECL_STMT for the reference itself. */
4956 if (at_function_scope_p ())
4957 add_decl_stmt (decl);
4958
4959 if (TREE_CODE (decl) == VAR_DECL)
4960 layout_var_decl (decl);
4961
4962 /* Output the assembler code and/or RTL code for variables and functions,
4963 unless the type is an undefined structure or union.
4964 If not, it will get done when the type is completed. */
4965 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
4966 {
4967 if (TREE_CODE (decl) == VAR_DECL)
4968 maybe_commonize_var (decl);
4969
4970 make_rtl_for_nonlocal_decl (decl, init, asmspec);
4971
4972 if (TREE_CODE (type) == FUNCTION_TYPE
4973 || TREE_CODE (type) == METHOD_TYPE)
4974 abstract_virtuals_error (decl,
4975 strip_array_types (TREE_TYPE (type)));
4976 else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
4977 {
4978 /* If it's either a pointer or an array type, strip through all
4979 of them but the last one. If the last is an array type, issue
4980 an error if the element type is abstract. */
4981 while (POINTER_TYPE_P (TREE_TYPE (type))
4982 || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
4983 type = TREE_TYPE (type);
4984 if (TREE_CODE (type) == ARRAY_TYPE)
4985 abstract_virtuals_error (decl, TREE_TYPE (type));
4986 }
4987 else
4988 abstract_virtuals_error (decl, type);
4989
4990 if (TREE_CODE (decl) == FUNCTION_DECL
4991 || TREE_TYPE (decl) == error_mark_node)
4992 /* No initialization required. */
4993 ;
4994 else if (DECL_EXTERNAL (decl)
4995 && ! (DECL_LANG_SPECIFIC (decl)
4996 && DECL_NOT_REALLY_EXTERN (decl)))
4997 {
4998 if (init)
4999 DECL_INITIAL (decl) = init;
5000 }
5001 else
5002 {
5003 /* A variable definition. */
5004 if (DECL_FUNCTION_SCOPE_P (decl))
5005 {
5006 /* This is a local declaration. */
5007 maybe_inject_for_scope_var (decl);
5008 /* Initialize the local variable. */
5009 if (processing_template_decl )
5010 {
5011 if (init || DECL_INITIAL (decl) == error_mark_node)
5012 DECL_INITIAL (decl) = init;
5013 }
5014 else if (!TREE_STATIC (decl))
5015 initialize_local_var (decl, init);
5016 }
5017
5018 /* If a variable is defined, and then a subsequent
5019 definintion with external linkage is encountered, we will
5020 get here twice for the same variable. We want to avoid
5021 calling expand_static_init more than once. For variables
5022 that are not static data members, we can call
5023 expand_static_init only when we actually process the
5024 initializer. It is not legal to redeclare a static data
5025 member, so this issue does not arise in that case. */
5026 if (var_definition_p && TREE_STATIC (decl))
5027 expand_static_init (decl, init);
5028 }
5029 finish_end0:
5030
5031 /* Undo call to `pushclass' that was done in `start_decl'
5032 due to initialization of qualified member variable.
5033 I.e., Foo::x = 10; */
5034 {
5035 tree context = CP_DECL_CONTEXT (decl);
5036 if (context
5037 && TYPE_P (context)
5038 && (TREE_CODE (decl) == VAR_DECL
5039 /* We also have a pushclass done that we need to undo here
5040 if we're at top level and declare a method. */
5041 || TREE_CODE (decl) == FUNCTION_DECL)
5042 /* If size hasn't been set, we're still defining it,
5043 and therefore inside the class body; don't pop
5044 the binding level.. */
5045 && COMPLETE_TYPE_P (context)
5046 && context == current_class_type )
5047 pop_nested_class ();
5048 }
5049 }
5050
5051 /* If a CLEANUP_STMT was created to destroy a temporary bound to a
5052 reference, insert it in the statement-tree now. */
5053 if (cleanup)
5054 add_stmt (cleanup);
5055
5056 finish_end:
5057
5058 if (was_readonly)
5059 TREE_READONLY (decl) = 1;
5060
5061 /* If this was marked 'used', be sure it will be output. */
5062 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
5063 mark_referenced (DECL_ASSEMBLER_NAME (decl));
5064 }
因为在 initialize_array 的 6809 行, decl 的上下文( context )被暂时清空,因此在 4956 行的 at_function_scope_p 返回 false 。而 4968 行的 maybe_commonize_var 处理这么一个情况:声明在一个内联函数中的局部静态变量;或我们有一个弱定义( weak definition ),对此,编译器必需努力在链接时刻仅为该变量构建一个实例。
那么回到 cp_finish_decl ,在 4970 行,在 make_rtl_for_nonlocal_decl 里,局部变量 defer_p 在 4658 行被设置为 true ,因为这个 VAR_DECL 设置了标记 DECL_VIRTUAL_P ;另外在调用时, asmspec 是 NULL 。因此在这个函数中没有做实质性的处理。
接着,因为 5026 行的 var_definition_p 是 true ,调用 expand_static_init ,不过因为 vtable 的 ARRAY_TYPE 没有设置标记 YPE_NEEDS_CONSTRUCTING ,该函数立即返回。
最后, 5052 行的 cleanup 可能不是 NULL ,如果我们在处理引用(这里它是 NULL )。从 cp_finish_decl 退出,我们回到下面的 finish_struct_1 中。