5.12.5.2.2.2.1.3.2. 具现基类——完成
在处理完所有的基类后(基类被串接起来),在 instantiate_class_template 的 5452 行,调用 xref_basetype 来填充其 binfo 部分,其中实参 ref 是派生类的 RECORD_TYPE ,而 base_list 包含了基类的 RECORD_TYPE ,及其访问属性。
基类的 RECORD_TYPE 是尚未完成的,因为其 type 域是空的,因此它需要首先通过在 xref_basetype 9645 行的 complete_type_or_else 来完成这个域。
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 already issued an error. */
153 return NULL_TREE;
154 else if (!COMPLETE_TYPE_P (type))
155 {
156 cxx_incomplete_type_diagnostic (value, type, diag_type);
157 return NULL_TREE;
158 }
159 else
160 return type;
161 }
看到在函数的开头, complete_type 被递归调用(我们从为派生类调用的 complete_type 中来到这里)。在 complete_type 中,为基类亦调用了 instantiate_class_template 来对其具现。如果基类亦是从某个模板类派生,这个过程亦为该基类重复。直到找到最底层的模板类(我们现在只看到具现模板类的前半部分,在后半部分模板类要调用 finish_struct 来完成 RECORD_TYPE 节点),或者最底层非模板类(这样的类型已经调用过 finish_struct ,其 RECORD_TYPE 节点已经完成处理)。在这里我们跳过在 complete_type 中基类处理的细节,假定之后其 RECORD_TYPE 已经完成处理。
xref_basetype 的细节可以参考前面的章节,对于我们的例子,执行深拷贝,因为基类是一个 RECORD_TYPE 节点。我们得到如下的布局。
( 点此打开 )
5.12.5.2.2.2.1.3.3. 完成派生类的 RECORD_TYPE – 成员的替代
现在基类的具现体已经就绪,并且该派生类的 binfo 也已设置,接下来需要填入该类的成员,因为这里的 type 是一个对应具现体的空的 RECORD_TYPE 。进一步的派生类中的某些成员可能依赖于模板参数,它们也需要进行实参替换。如何产生这些类型值得了解。该处理函数虽然长,但相当明白。
instantiate_class_template (continue)
5458 /* Now that our base classes are set up, enter the scope of the
5459 class, so that name lookups into base classes, etc. will work
5460 correctly. This is precisely analogous to what we do in
5461 begin_class_definition when defining an ordinary non-template
5462 class. */
5463 pushclass (type);
5464
5465 /* Now members are processed 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 new CLASSTYPE_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 member is a class template, then -- even after
5486 substituition -- there may be dependent types in the
5487 template argument list for the class. We increment
5488 PROCESSING_TEMPLATE_DECL so that dependent_type_p, as
5489 that function will assume that no types are dependent
5490 when outside of a template. */
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 class nested within a template class.)
5506 This behavior is required for
5507 maybe_process_partial_specialization to work
5508 correctly, but is not accurate in this case;
5509 the TAG is not an instantiation of anything.
5510 (The corresponding TEMPLATE_DECL is an
5511 instantiation, but the TYPE is not.) */
5512 CLASSTYPE_USE_TEMPLATE (newtag) = 0;
5513
5514 /* Now, we call pushtag to put this NEWTAG into the scope of
5515 TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
5516 pushtag calling push_template_decl. We don't have to do
5517 this for enums because it 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 new TYPE_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 and line for this declaration, to
5548 assist in error message reporting. Since we
5549 called push_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. If R is invalid, then it is
5578 replaced by error_mark_node so that it will not be
5579 added to TYPE_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 is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
5592 such a thing will already have been added to the field
5593 list by tsubst_enum in finish_member_declaration in the
5594 CLASSTYPE_NESTED_UTDS case 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 new CLASSTYPE_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 call to 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 /* Trick make_friend_class into realizing that the friend
5635 we're adding is a template, not an ordinary class. It's
5636 important that we use make_friend_class since it will
5637 perform some error-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 new DECL_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 and line number information to whatever is given for
5664 the class itself. This puts error messages involving generated
5665 implicit functions at a predictable point, and the same point
5666 that would be used for non-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);
注意到在该类中声明的成员被 CLASSTYPE_DECL_LIST 域以 tree_list 节点的形式记录起来。在这些 tree_list 节点中, TREE_PURPOSE 域记录了其所属的类(如果是友元声明则是 NULL ),而 TREE_VALUE 域保存了声明本身。
在前面的章节中看到,在模板类中声明的实体亦被视为模板声明,连同产生 TEMPLATE_DECL 。在具现的过程中,模板实参将替换模板形参。
5.12.5.2.2.2.1.3.4. 完成派生类的 RECORD_TYPE – 修正内联方法
因为模板类的具现对应的 RECORD_TYPE 是一个普通的类,在 5671 行必须调用 finish_struct_1 来完成其定义。
4997 void
4998 finish_struct_1 (tree t) in class.c
4999 {
5001 tree x;
5002 /* A TREE_LIST. The TREE_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 was previously laid out as a forward reference,
5018 make sure we lay it out again. */
5019 TYPE_SIZE (t) = NULL_TREE;
5020 CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
5021
5022 fixup_inline_methods (t);
5023
5024 /* Make assumptions about 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-class semantic processing: checking the validity of the
5031 bases and members and add implicitly generated methods. */
5032 check_bases_and_members (t);
同样,记得对于内联方法,在对应的 FUNCTION_DECL 节点中,其 template_info 域填充有模板信息。上面的成员替换为成员正确地进行了实参替换,但是某些关系尚未相应地更新。
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 member functions. */
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 }
记得内联方法的函数体被缓存在 DECL_PENDING_INLINE_INFO 中。在具现时,内联方法的实参已经被替换入其函数体,但其 context 域并未触及,在完成替换后,需要为内联方法将其更新(构建的新节点)。
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. 完成派生类的 RECORD_TYPE – 验证基类
在这一点上,基类及成员的实参替换被恰当地完成了,不过没有对模板的具现进行类级别的语义检查。这个语义检查应尽快进行。这里就是尽早执行语义检查的点。
4145 static void
4146 check_bases_and_members (tree t) in class.c
4147 {
4148 /* Nonzero if we are not allowed to generate a default constructor
4149 for this case. */
4150 int cant_have_default_ctor;
4151 /* Nonzero if the implicitly generated copy constructor should take
4152 a non-const reference argument. */
4153 int cant_have_const_ctor;
4154 /* Nonzero if the the implicitly generated assignment operator
4155 should take a non-const reference argument. */
4156 int no_const_asn_ref;
4157 tree access_decls;
4158
4159 /* By default, we use 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 the base-classes. */
4166 check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
4167 &no_const_asn_ref);
如果模板类包含(派生)基类(记得基类也可以是模板类,比如我们的“ SmallObject ”),是时候检查派生类与基类间是否有不符合的地方。
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 aggregate cannot 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 out what base we're looking at. */
1133 base_binfo = TREE_VEC_ELT (binfos, i);
1134 basetype = TREE_TYPE (base_binfo);
1135
1136 /* If the type of basetype 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 pretend that 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 of virtual functions but non-virtual
1156 dtor is handled in finish_struct_1. */
1157 if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype)
1158 && TYPE_HAS_DESTRUCTOR (basetype))
1159 warning ("base class `%#T' has a non-virtual destructor",
1160 basetype);
1161
1162 /* If the base class doesn't have copy constructors or
1163 assignment operators that take const references, then the
1164 derived class cannot have such a 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, if the base class doesn't have a default
1172 constructor, then the derived class won't have an
1173 automatically generated default 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 virtual base 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 if there is more than one nearly empty base, then the
1190 derived class is not nearly empty either. */
1191 CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
1192 else
1193 /* Remember we've seen one. */
1194 seen_non_virtual_nearly_empty_base_p = 1;
1195 }
1196 else if (!is_empty_class (basetype))
1197 /* If the base class is not empty or nearly empty, then this
1198 class cannot be nearly empty. */
1199 CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
1200
1201 /* A lot of properties 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 }
在该次调用的实参中, cant_have_default_ctor 是非 0 值,如果基类没有缺省构造函数; cant_have_const_ctor 是非 0 值,如果基类没有使用引用常量的拷贝构造函数,而 no_const_asn_ref 是非 0 值,如果基类没有使用引用常量的赋值操作符。