Studying note of GCC-3.4.6 source (135)
来源:互联网 发布:sql 的not in中的为空 编辑:程序博客网 时间:2024/06/05 22:30
5.12.5.2.2.2.1.3.2. Instantiatebase class – finish
After processing the bases (they are chained tegother), in instantiate_class_templateat line 5452, xref_basetypeis called to fill the binfo part, in which parameter ref is the RECORD_TYPE of thederived, and base_listcontains the RECORD_TYPE of the bases and their accessbility.
The RECORD_TYPE of base is incomplete as the type field is empty, so it needs becompleted first by complete_type_or_else at line 9645 in xref_basetype.
4210 #define complete_type_or_else(T,V)(complete_type_or_diagnostic ((T), (V), 0))
147 tree
148 complete_type_or_diagnostic (tree type,tree value, int diag_type) in typeck.c
149 {
150 type = complete_type (type);
151 if (type == error_mark_node)
152 /* We alreadyissued an error. */
153 returnNULL_TREE;
154 else if (!COMPLETE_TYPE_P (type))
155 {
156 cxx_incomplete_type_diagnostic (value,type, diag_type);
157 returnNULL_TREE;
158 }
159 else
160 returntype;
161 }
See complete_type is recursed at the beginning the function(we come here inside the complete_type calledfor the derived), in which also calls instantiate_class_template to instantiate thebase. If the base also derives from certain template class, this procedurewould be repeated till arrives at the bottom template class (we just see thefirst part of the instantiating, in the rear part the template will invoke finish_structto complete its RECORD_TYPE), or the bottom non-template class (such type hasinvoked finsih_struct,its RECORD_TYPE is complete). Here we just skip the detail of the handling ofthe base class in complete_type and assume this node ofRECORD_TYPE is completed after that.
The detail of xref_basetypecan be seen in previous section, for our case, real deep copy is executed asbase class is a node of RECORD_TYPE. And it gets following layout.
(Clickhere for open)
5.12.5.2.2.2.1.3.3. Finish the derivedRECORD_TYPE –members subsititution
Now the instantiation of base class is ready, and the binfo of thederived is setup, following it needs fill in the member of the class as typehere is an empty RECORD_TYPE for the instantiation. Further the member of thederived class as some of them may depend on the template parameters, so theyneed be subsitituted by the arguments too. It’s worth our attention to see howto generate these types. The function though is lengthy but quite straightforward.
instantiate_class_template (continue)
5458 /* Now that ourbase classes are set up, enter the scope of the
5459 class, so that name lookupsinto base classes, etc. will work
5460 correctly. This is preciselyanalogous to what we do in
5461 begin_class_definition whendefining an ordinary non-template
5462 class. */
5463 pushclass (type);
5464
5465 /* Now members areprocessed in the order of declaration. */
5466 for (member =CLASSTYPE_DECL_LIST (pattern);
5467 member; member = TREE_CHAIN (member))
5468 {
5469 tree t = TREE_VALUE (member);
5470
5471 if (TREE_PURPOSE (member))
5472 {
5473 if (TYPE_P (t))
5474 {
5475 /* Build newCLASSTYPE_NESTED_UTDS. */
5476
5477 tree tag = t;
5478 tree name = TYPE_IDENTIFIER (tag);
5479 tree newtag;
5480 bool class_template_p;
5481
5482 class_template_p = (TREE_CODE (tag) !=ENUMERAL_TYPE
5483 &&TYPE_LANG_SPECIFIC (tag)
5484 &&CLASSTYPE_IS_TEMPLATE (tag));
5485 /* If the memberis a class template, then -- even after
5486 substituition -- theremay be dependent types in the
5487 template argument listfor the class. We increment
5488 PROCESSING_TEMPLATE_DECLso that dependent_type_p, as
5489 that function will assume that no typesare dependent
5490 when outside of atemplate. */
5491 if (class_template_p)
5492 ++processing_template_decl;
5493 newtag = tsubst (tag, args, tf_error,NULL_TREE);
5494 if (class_template_p)
5495 --processing_template_decl;
5496 if (newtag == error_mark_node)
5497 continue;
5498
5499 if (TREE_CODE (newtag) !=ENUMERAL_TYPE)
5500 {
5501 if (class_template_p)
5502 /*Unfortunately, lookup_template_class sets
5503 CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
5504 instantiation(i.e., for the type of a member
5505 template classnested within a template class.)
5506 This behavior isrequired for
5507 maybe_process_partial_specialization to work
5508 correctly, but isnot accurate in this case;
5509 the TAG is not aninstantiation of anything.
5510 (The correspondingTEMPLATE_DECL is an
5511 instantiation, butthe TYPE is not.) */
5512 CLASSTYPE_USE_TEMPLATE (newtag) =0;
5513
5514 /* Now, wecall pushtag to put this NEWTAG into the scope of
5515 TYPE. We first set up theIDENTIFIER_TYPE_VALUE to avoid
5516 pushtag callingpush_template_decl. We don't have to do
5517 this for enums becauseit will already have been done in
5518 tsubst_enum. */
5519 if (name)
5520 SET_IDENTIFIER_TYPE_VALUE (name,newtag);
5521 pushtag (name,newtag, /*globalize=*/0);
5522 }
5523 } // end if (TYPE_P (t))
5524 else if (TREE_CODE (t) == FUNCTION_DECL
5525 || DECL_FUNCTION_TEMPLATE_P (t))
5526 {
5527 /* Build newTYPE_METHODS. */
5528 tree r;
5529
5530 if (TREE_CODE (t) == TEMPLATE_DECL)
5531 ++processing_template_decl;
5532 r = tsubst (t, args, tf_error,NULL_TREE);
5533 if (TREE_CODE (t) == TEMPLATE_DECL)
5534 --processing_template_decl;
5535 set_current_access_from_decl (r);
5536 grok_special_member_properties (r);
5537 finish_member_declaration(r);
5538 }
5539 else
5540 {
5541 /* Build new TYPE_FIELDS. */
5542
5543 if (TREE_CODE (t) != CONST_DECL)
5544 {
5545 tree r;
5546
5547 /* The the file andline for this declaration, to
5548 assist in errormessage reporting. Since we
5549 calledpush_tinst_level above, we don't need to
5550 restore these. */
5551 input_location = DECL_SOURCE_LOCATION (t);
5552
5553 if (TREE_CODE (t) == TEMPLATE_DECL)
5554 ++processing_template_decl;
5555 r = tsubst (t, args, tf_error |tf_warning, NULL_TREE);
5556 if (TREE_CODE (t) == TEMPLATE_DECL)
5557 --processing_template_decl;
5558 if (TREE_CODE (r) == VAR_DECL)
5559 {
5560 tree init;
5561
5562 if (DECL_INITIALIZED_IN_CLASS_P(r))
5563 init = tsubst_expr (DECL_INITIAL(t), args,
5564 tf_error | tf_warning,NULL_TREE);
5565 else
5566 init = NULL_TREE;
5567
5568 finish_static_data_member_decl
5569 (r, init, /*asmspec_tree=*/NULL_TREE, /*flags=*/0);
5570
5571 if (DECL_INITIALIZED_IN_CLASS_P (r))
5572 check_static_variable_definition(r, TREE_TYPE (r));
5573 }
5574 else if (TREE_CODE (r) == FIELD_DECL)
5575 {
5576 /*Determine whether R has a valid type and can be
5577 completed later. IfR is invalid, then it is
5578 replaced byerror_mark_node so that it will not be
5579 added toTYPE_FIELDS. */
5580 tree rtype = TREE_TYPE (r);
5581 if (can_complete_type_without_circularity(rtype))
5582 complete_type(rtype);
5583
5584 if (!COMPLETE_TYPE_P (rtype))
5585 {
5586 cxx_incomplete_type_error (r, rtype);
5587 r = error_mark_node;
5588 }
5589 }
5590
5591 /* If it isa TYPE_DECL for a class-scoped ENUMERAL_TYPE,
5592 such a thing willalready have been added to the field
5593 list by tsubst_enum infinish_member_declaration in the
5594 CLASSTYPE_NESTED_UTDScase above. */
5595 if (!(TREE_CODE (r) == TYPE_DECL
5596 && TREE_CODE (TREE_TYPE(r)) == ENUMERAL_TYPE
5597 && DECL_ARTIFICIAL (r)))
5598 {
5599 set_current_access_from_decl (r);
5600 finish_member_declaration(r);
5601 }
5602 }
5603 }
5604 } // if (TREE_PURPOSE (member))
5605 else
5606 {
5607 if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P(t))
5608 {
5609 /* Build newCLASSTYPE_FRIEND_CLASSES. */
5610
5611 tree friend_type = t;
5612 tree new_friend_type;
5613
5614 if (TREE_CODE (friend_type) ==TEMPLATE_DECL)
5615 new_friend_type = tsubst_friend_class(friend_type, args);
5616 else if (uses_template_parms(friend_type))
5617 new_friend_type = tsubst(friend_type, args,
5618 tf_error |tf_warning, NULL_TREE);
5619 else if (CLASSTYPE_USE_TEMPLATE(friend_type))
5620 new_friend_type = friend_type;
5621 else
5622 {
5623 tree ns = decl_namespace_context (TYPE_MAIN_DECL(friend_type));
5624
5625 /* The callto xref_tag_from_type does injection for friend
5626 classes. */
5627 push_nested_namespace(ns);
5628 new_friend_type =
5629 xref_tag_from_type (friend_type,NULL_TREE, 1);
5630 pop_nested_namespace (ns);
5631 }
5632
5633 if (TREE_CODE (friend_type) ==TEMPLATE_DECL)
5634 /* Trickmake_friend_class into realizing that the friend
5635 we're adding is atemplate, not an ordinary class. It's
5636 important that we usemake_friend_class since it will
5637 perform someerror-checking and output cross-reference
5638 information. */
5639 ++processing_template_decl;
5640
5641 if (new_friend_type != error_mark_node)
5642 make_friend_class (type,new_friend_type,
5643 /*complain=*/false);
5644
5645 if (TREE_CODE (friend_type) ==TEMPLATE_DECL)
5646 --processing_template_decl;
5647 }
5648 else
5649 {
5650 /* Build newDECL_FRIENDLIST. */
5651 tree r;
5652
5653 if (TREE_CODE (t) == TEMPLATE_DECL)
5654 ++processing_template_decl;
5655 r = tsubst_friend_function (t, args);
5656 if (TREE_CODE (t) == TEMPLATE_DECL)
5657 --processing_template_decl;
5658 add_friend (type, r, /*complain=*/false);
5659 }
5660 }
5661 }
5662
5663 /* Set the file andline number information to whatever is given for
5664 the class itself. This putserror messages involving generated
5665 implicit functions at apredictable point, and the same point
5666 that would be used fornon-template classes. */
5667 typedecl = TYPE_MAIN_DECL (type);
5668 input_location = DECL_SOURCE_LOCATION (typedecl);
5669
5670 unreverse_member_declarations(type);
5671 finish_struct_1(type);
Notice that members declared within the class are recorded by nodeof tree_list and chained in field of CLASSTYPE_DECL_LIST. In the tree_listnode, TREE_PURPOSE field records the class it belongs to (and NULL if it is thefriend declaration), and TREE_VALUE field holds the declaration itself.
Also see in previous sections, entities declared within the classtemplate are considered as template declarations too, with TEMPLATE_DECLgenerated. During instantiation, the real template arguments should substitutethe template parameters.
5.12.5.2.2.2.1.3.4. Finish the derivedRECORD_TYPE – fixup inline methods
As RECORD_TYPE for the class template instantiation is a normalclass, at line 5671 finish_struct_1 must be invoked to finish thedefinition.
4997 void
4998 finish_struct_1 (tree t) in class.c
4999 {
5001 tree x;
5002 /* A TREE_LIST. TheTREE_VALUE of each node is a FUNCTION_DECL. */
5003 tree virtuals = NULL_TREE;
5004 int n_fields = 0;
5005 tree vfield;
5006
5007 if (COMPLETE_TYPE_P (t))
5008 {
5009 if (IS_AGGR_TYPE (t))
5010 error ("redefinition of `%#T'",t);
5011 else
5012 abort ();
5013 popclass ();
5014 return;
5015 }
5016
5017 /* If this type waspreviously laid out as a forward reference,
5018 make sure we lay it outagain. */
5019 TYPE_SIZE (t) = NULL_TREE;
5020 CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
5021
5022 fixup_inline_methods(t);
5023
5024 /* Make assumptionsabout the class; we'll reset the flags if
5025 necessary. */
5026 CLASSTYPE_EMPTY_P (t) = 1;
5027 CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
5028 CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
5029
5030 /* Do end-of-classsemantic processing: checking the validity of the
5031 bases and members and addimplicitly generated methods. */
5032 check_bases_and_members(t);
Also, remember that for inline method, the associated FUNCTION_DECLnode has its template_infofield filled with the template information. The member subsititution abovesubsititues the arguments for methods appropriately, but some relations arestill not updated accordingly.
4323 static void
4324 fixup_inline_methods (tree type) in class.
4325 {
4326 tree method = TYPE_METHODS (type);
4327
4328 if (method && TREE_CODE (method) ==TREE_VEC)
4329 {
4330 if (TREE_VEC_ELT (method, 1))
4331 method = TREE_VEC_ELT (method, 1);
4332 else if (TREE_VEC_ELT (method, 0))
4333 method = TREE_VEC_ELT (method, 0);
4334 else
4335 method = TREE_VEC_ELT (method, 2);
4336 }
4337
4338 /* Do inline memberfunctions. */
4339 for (;method; method = TREE_CHAIN (method))
4340 fixup_pending_inline(method);
4341
4342 /* Do friends. */
4343 for (method =CLASSTYPE_INLINE_FRIENDS (type);
4344 method;
4345 method = TREE_CHAIN (method))
4346 fixup_pending_inline (TREE_VALUE (method));
4347 CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
4348 }
Remember the body of inline method is cached withinDECL_PENDING_INLINE_INFO. For arguments of the inline method, they have beensubsititued with those at instantiating, but the context field remains untouched, itneeds updated for the inline method after subsititution (the new nodescreated).
4306 static void
4307 fixup_pending_inline (tree fn) in class.
4308 {
4309 if (DECL_PENDING_INLINE_INFO (fn))
4310 {
4311 tree args = DECL_ARGUMENTS (fn);
4312 while(args)
4313 {
4314 DECL_CONTEXT (args) = fn;
4315 args = TREE_CHAIN (args);
4316 }
4317 }
4318 }
5.12.5.2.2.2.1.3.5. Finish the derivedRECORD_TYPE – verify base classes
At this point, the base class, and the members are subsitituted withargument appropriately, but no semantic checking at the class level isperformed for the template instantiation. This semantic checking should betaken as soon as possible. Here is the most early point the semantic checkingcan be performed.
4145 static void
4146 check_bases_and_members (tree t) in class.c
4147 {
4148 /* Nonzero if weare not allowed to generate a default constructor
4149 for this case. */
4150 int cant_have_default_ctor;
4151 /* Nonzero if theimplicitly generated copy constructor should take
4152 a non-const reference argument. */
4153 int cant_have_const_ctor;
4154 /* Nonzero if thethe implicitly generated assignment operator
4155 should take a non-constreference argument. */
4156 int no_const_asn_ref;
4157 tree access_decls;
4158
4159 /* By default, weuse const reference arguments and generate default
4160 constructors. */
4161 cant_have_default_ctor = 0;
4162 cant_have_const_ctor = 0;
4163 no_const_asn_ref = 0;
4164
4165 /* Check all thebase-classes. */
4166 check_bases (t,&cant_have_default_ctor, &cant_have_const_ctor,
4167 &no_const_asn_ref);
If the class template contains (derives) base classes (remember thebase classes may be class template too, see our example of “SmallObject”), itis time to see there is any flaw between the class and the base classes.
1109 static void
1110 check_bases (tree t, in class.c
1111 int* cant_have_default_ctor_p,
1112 int* cant_have_const_ctor_p,
1113 int* no_const_asn_ref_p)
1114 {
1115 int n_baseclasses;
1116 int i;
1117 int seen_non_virtual_nearly_empty_base_p;
1118 tree binfos;
1119
1120 binfos = TYPE_BINFO_BASETYPES (t);
1121 n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
1122 seen_non_virtual_nearly_empty_base_p = 0;
1123
1124 /* An aggregatecannot have baseclasses. */
1125 CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
1126
1127 for (i = 0; i < n_baseclasses; ++i)
1128 {
1129 tree base_binfo;
1130 tree basetype;
1131
1132 /* Figure outwhat base we're looking at. */
1133 base_binfo = TREE_VEC_ELT (binfos, i);
1134 basetype = TREE_TYPE (base_binfo);
1135
1136 /* If the type ofbasetype is incomplete, then we already
1137 complained about that fact(and we should have fixed it up as
1138 well). */
1139 if (!COMPLETE_TYPE_P (basetype))
1140 {
1141 int j;
1142 /* The base type is of incomplete type. It is
1143 probably best to pretendthat it does not
1144 exist. */
1145 if (i == n_baseclasses-1)
1146 TREE_VEC_ELT (binfos, i) = NULL_TREE;
1147 TREE_VEC_LENGTH (binfos) -= 1;
1148 n_baseclasses -= 1;
1149 for (j = i; j+1 < n_baseclasses; j++)
1150 TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
1151 continue;
1152 }
1153
1154 /* Effective C++rule 14. We only need to check TYPE_POLYMORPHIC_P
1155 here because the case ofvirtual functions but non-virtual
1156 dtor is handled infinish_struct_1. */
1157 if (warn_ecpp && ! TYPE_POLYMORPHIC_P(basetype)
1158 && TYPE_HAS_DESTRUCTOR(basetype))
1159 warning ("base class `%#T' has anon-virtual destructor",
1160 basetype);
1161
1162 /* If the baseclass doesn't have copy constructors or
1163 assignment operators thattake const references, then the
1164 derived class cannot have sucha member automatically
1165 generated. */
1166 if (! TYPE_HAS_CONST_INIT_REF (basetype))
1167 *cant_have_const_ctor_p = 1;
1168 if (TYPE_HAS_ASSIGN_REF (basetype)
1169 && !TYPE_HAS_CONST_ASSIGN_REF(basetype))
1170 *no_const_asn_ref_p = 1;
1171 /* Similarly, ifthe base class doesn't have a default
1172 constructor, then thederived class won't have an
1173 automatically generateddefault constructor. */
1174 if (TYPE_HAS_CONSTRUCTOR (basetype)
1175 && !TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
1176 {
1177 *cant_have_default_ctor_p = 1;
1178 if (! TYPE_HAS_CONSTRUCTOR (t))
1179 pedwarn ("base`%T' with only non-default constructor in class without a constructor",
1180 basetype);
1181 }
1182
1183 if (TREE_VIA_VIRTUAL (base_binfo))
1184 /* A virtualbase does not effect nearly emptiness. */
1185 ;
1186 else if (CLASSTYPE_NEARLY_EMPTY_P(basetype))
1187 {
1188 if (seen_non_virtual_nearly_empty_base_p)
1189 /* And ifthere is more than one nearly empty base, then the
1190 derived class is notnearly empty either. */
1191 CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
1192 else
1193 /* Rememberwe've seen one. */
1194 seen_non_virtual_nearly_empty_base_p =1;
1195 }
1196 else if (!is_empty_class (basetype))
1197 /* If the baseclass is not empty or nearly empty, then this
1198 class cannot be nearlyempty. */
1199 CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
1200
1201 /* A lot ofproperties from the bases also apply to the derived
1202 class. */
1203 TYPE_NEEDS_CONSTRUCTING(t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
1204 TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
1205 |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR(basetype);
1206 TYPE_HAS_COMPLEX_ASSIGN_REF (t)
1207 |= TYPE_HAS_COMPLEX_ASSIGN_REF(basetype);
1208 TYPE_HAS_COMPLEX_INIT_REF(t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
1209 TYPE_POLYMORPHIC_P (t) |=TYPE_POLYMORPHIC_P (basetype);
1210 CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
1211 |= CLASSTYPE_CONTAINS_EMPTY_CLASS_P(basetype);
1212 }
1213 }
Among the arguments in the invocation, cant_have_default_ctor is nonzero ifbase classes have no default constructor, cant_have_const_ctor is nonzero if base classeshave no copy constructor that takes constant reference, and no_const_asn_refis nonzero if base classes have no assignment operator that takes constantreference.
- Studying note of GCC-3.4.6 source (135)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (8)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (10 cont1)
- Studying note of GCC-3.4.6 source (10 cont2)
- Studying note of GCC-3.4.6 source (10 cont3)
- Studying note of GCC-3.4.6 source (10 cont4)
- Studying note of GCC-3.4.6 source (11)
- Studying note of GCC-3.4.6 source (12)
- Studying note of GCC-3.4.6 source (13)
- arduino基本知识
- 实现无session集群的负载均衡
- 近期项目总结之随机数
- 运行时动态创建报表(二)他山之石
- Linux内核设计与实现读书笔记(6)-下半部和推后执行的工作
- Studying note of GCC-3.4.6 source (135)
- 参数传递
- 小儿科备忘一下
- 成功之道
- 单音符,双语调,流年迁徙、忘尘埃
- 页面第一个控件获得焦点(js实现)
- 影响力
- 啊这种
- wcf创建及实现过程