GCC-3.4.6源代码学习笔记(141-续2)
来源:互联网 发布:云栈菜鸟淘宝打印组件 编辑:程序博客网 时间:2024/06/07 02:59
然后调用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 aninitializer is present, DECL_INITIAL has been
4474 error_mark_node, to indicatethat 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 goingto 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 havealready 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' maynot 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' haveincomplete type", decl);
4496 init = NULL_TREE;
4497 }
4498 else if (TREE_CODE (type) != ARRAY_TYPE&& !COMPLETE_TYPE_P (type))
4499 {
4500 error ("`%D' has incompletetype", 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 declarationof the form
4522 T x = { a };
4523 is equivalent to
4524 T x = a;
4525
4526 reshape_init will complain about the extrabraces,
4527 and doesn't do anything useful in the casewhere 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 cannotbe 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) indecl.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 theinitializer is brace-enclosed, pull initializers from the
4284 enclosed elements. Advancepast 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-aggregatetype 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 invalidto initialize a non-aggregate type with a
4309 brace-enclosedinitializer. */
4310 if (brace_enclosed_p)
4311 {
4312 error ("brace-enclosed initializerused 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 returnold_init;
4321 }
4322
4323 /* [dcl.init.aggr]
4324
4325 All implicit type conversions(clause _conv_) are considered when
4326 initializing the aggregatemember with an initializer from an
4327 initializer-list. If theinitializer can initialize a member,
4328 the member is initialized.Otherwise, if the member is itself a
4329 non-empty subaggregate, braceelision is assumed and the
4330 initializer is considered forthe initialization of the first
4331 member of thesubaggregate. */
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 returnold_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 aCONSTRUCTOR 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 moreinitializers
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 /* Theinitializers 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 aremore 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 aroundinitializer");
4451 }
4452
4453 returnnew_init;
4454 }
看到对于聚合类型的成员,4333行确认初始值的类型能被转换到成员的类型。对于数组,下面的reshape_init_array遍历成员,使用reshape_init为每个成员验证及重塑初始值。而对于非聚合类型成员,初始值立即被返回。
4203 static bool
4204 reshape_init_array (tree elt_type, treemax_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 zeroextended. */
4216 else
4217 max_index_cst = tree_low_cst (convert(size_type_node, max_index), 1);
4218 }
4219
4220 /* Loop until thereare 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 returnfalse;
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 (GNUextension). */
4237 if (TREE_CODE (designated_index) ==IDENTIFIER_NODE)
4238 {
4239 error ("name `%D' used in aGNU-style designated "
4240 "initializer for anarray", 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 anarray type without a specific bound, deduce the
4540 arraysize 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 gotoinitialize_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' withuninitialized const members", decl);
4600 if (CLASSTYPE_REF_FIELDS_NEED_INIT(core_type))
4601 error ("structure `%D' withuninitialized 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 returninit_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) intypeck2.c
412 {
413 tree value, type;
414
415 /* If variable'stype was invalidly declared, just ignore it. */
416
417 type = TREE_TYPE (decl);
418 if (TREE_CODE (type) == ERROR_MARK)
419 returnNULL_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 thespecified initializer into an expression. */
451 value = digest_init(type, init, (tree *) 0);
452 /* If theinitializer is not a constant, fill in DECL_INITIAL with
453 the bits that areconstant, and then return an expression that
454 will perform thedynamic initialization. */
455 if (value != error_mark_node
456 && (! TREE_CONSTANT (value)
457 || ! initializer_constant_valid_p (value,TREE_TYPE (value))))
458 returnsplit_nonconstant_init (decl, value);
459 /* If the value isa constant, just put it in DECL_INITIAL. If DECL
460 is an automaticvariable, the middle end will turn this into a
461 dynamicinitialization later. */
462 DECL_INITIAL (decl) = value;
463 returnNULL_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 enumtree_code code = TREE_CODE (type);
480 tree element = NULL_TREE;
481 tree old_tail_contents = NULL_TREE;
482 /* Nonzero if INITis a braced grouping. */
483 int raw_constructor;
484
485 /* By default,assume we use one element from a list.
486 We correct thislater 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 returnerror_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 substitutedduring instantiation. */
501 returninit;
502
503 /* We must stripthe outermost array type when completing the type,
504 because the itsbounds 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 returnerror_mark_node;
508
509 /* StripNON_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'tusing 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 returnelement;
526 }
527
528 /* Initializationof an array of chars from a string constant
529 optionallyenclosed 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 withparameter list");
538 returnerror_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 scalartypes, including conversions,
581 and signaturepointers 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 scalarvariable requires one element");
593 returnerror_mark_node;
594 }
595 init = element;
596 }
597 while(TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
598 {
599 pedwarn ("braces around scalarinitializer for `%T'", type);
600 init = CONSTRUCTOR_ELTS (init);
601 if (TREE_CHAIN (init))
602 pedwarn ("ignoring extrainitializers for `%T'", type);
603 init = TREE_VALUE (init);
604 }
605
606 returnconvert_for_initialization (0, type, init, LOOKUP_NORMAL,
607 "initialization", NULL_TREE, 0);
608 }
609
610 /* Come here onlyfor 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 returnerror_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' mustbe initialized by constructor, not by `%E'",
625 type, init);
626 returnerror_mark_node;
627 }
628 else if (raw_constructor)
629 return process_init_constructor (type, init,(tree *)0);
…
649 }
650
651 error ("invalid initializer");
652 returnerror_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 theelements of the result constructor,
675 in 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 thelist of elements to use for the initialization,
684 no matter how thedata was given to us. */
685
686 if (elts)
687 {
688 if (warn_missing_braces)
689 warning ("aggregate has a partlybracketed initializer");
690 tail = *elts;
691 }
692 else
693 tail = CONSTRUCTOR_ELTS (init);
694
695 /* Gobble as manyelements as needed, and make a constructor or initial value
696 for each elementof this aggregate. Chain them together in result.
697 If there are toofew, 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 asthere are. */
713 }
714 else
715 {
716 /* Vectors arelike 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 labeledinitializers");
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 returnnext1;
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 initializerfor array of empty elements");
745 /* Justignore 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'redone. */
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 /* Thedefault zero-initialization is fine for us; don't
778 addanything 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 zeroinitialization. */
911 && tail)
912 {
…
977 }
978
979 /* If argumentswere specified as a list, just remove the ones we used. */
980 if (elts)
981 *elts = tail;
982 /* If argumentswere specified as a constructor,
983 complain unlesswe used all the elements of the constructor. */
984 else if (tail)
985 pedwarn ("excess elements in aggregateinitializer");
986
987 if (erroneous)
988 returnerror_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 returnresult;
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 thisdeclaration to the statement-tree. This needs to happen
4954 after the call tocheck_initializer so that the DECL_STMT for a
4955 reference temp is added beforethe 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 theassembler code and/or RTL code for variables and functions,
4963 unless the type is anundefined structure or union.
4964 If not, it will get done whenthe 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 eithera pointer or an array type, strip through all
4979 of them but the last one. If the last is anarray type, issue
4980 an error if the element type isabstract. */
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 /* Noinitialization 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 withexternal linkage is encountered, we will
5020 get here twicefor the same variable. We want to avoid
5021 callingexpand_static_init more than once. For variables
5022 that are notstatic data members, we can call
5023 expand_static_init only when we actuallyprocess the
5024 initializer. Itis not legal to redeclare a static data
5025 member, so thisissue 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 membervariable.
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 /* Wealso have a pushclass done that we need to undo here
5040 if we're at top level and declare amethod. */
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_STMTwas created to destroy a temporary bound to a
5052 reference, insert it in thestatement-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 wasmarked '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中。
- GCC-3.4.6源代码学习笔记(141-续2)
- GCC-3.4.6源代码学习笔记(141-续1)
- GCC-3.4.6源代码学习笔记(10续2)
- GCC-3.4.6源代码学习笔记(25续2)
- GCC-3.4.6源代码学习笔记(26续2)
- GCC-3.4.6源代码学习笔记(48续2)
- GCC-3.4.6源代码学习笔记(139-续2)
- GCC-3.4.6源代码学习笔记(147-续2)
- GCC-3.4.6源代码学习笔记(141)
- GCC-3.4.6源代码学习笔记(10续1)
- GCC-3.4.6源代码学习笔记(10续3)
- GCC-3.4.6源代码学习笔记(10续4)
- GCC-3.4.6源代码学习笔记(19续)
- GCC-3.4.6源代码学习笔记(24续)
- GCC-3.4.6源代码学习笔记(25续1)
- GCC-3.4.6源代码学习笔记(26续1)
- GCC-3.4.6源代码学习笔记(48续)
- GCC-3.4.6源代码学习笔记(129 续)
- 晕,IBM网站竟然被黑
- 学习批处理命令
- 实例学习SQL的Select命令
- 基类与派生类对象的关系
- DLL自定义窗口类
- GCC-3.4.6源代码学习笔记(141-续2)
- MFC坐标转换
- Studying note of GCC-3.4.6 source (141 - cont 2)
- TIMER 定时器
- asterisk 中结合Freepbx 设置:禁止分机拨打长途电话或只能拨打内部分机(引自 voip88)
- 2010年的那些事儿
- cas实践应用
- Spring多线程注入问题
- H2各种URL