5.12.5.2.2.2.1.3. 为具现构建 RECORD_TYPE
最后,在 cp_parser_init_declarator 的 10181 行, cp_finish_decl 完成这个声明。因为它是在一个函数中的声明,在下面 4957 行,一个新的 DECL_STMT 被插入到对应的 stmt-tree ,之后我们得到如下的中间树。
( 点此打开 )
4786 void
4787 cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) in decl.c
4788 {
4789 tree type;
4790 tree ttype = NULL_TREE;
4791 tree cleanup;
4792 const char *asmspec = NULL;
4793 int was_readonly = 0;
4794 bool var_definition_p = false;
4795
4796 if (decl == error_mark_node)
4797 return ;
4798 else if (! decl)
4799 {
4800 if (init)
4801 error ("assignment (not initialization) in declaration");
4802 return ;
4803 }
4804
4805 my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
…
4821 type = TREE_TYPE (decl);
…
4844 /* Parameters are handled by store_parm_decls, not cp_finish_decl. */
4845 my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
…
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);
接下来需要由下面的 layout_var_decl 来完成该类型的定义。
4043 static void
4044 layout_var_decl (tree decl) in decl.c
4045 {
4046 tree type = TREE_TYPE (decl);
4047 #if 0
4048 tree ttype = target_type (type);
4049 #endif
4050
4051 /* If we haven't already layed out this declaration, do so now.
4052 Note that we must not call complete type for an external object
4053 because it's type might involve templates that we are not
4054 supposed to instantiate yet. (And it's perfectly valid to say
4055 `extern X x' for some incomplete type `X'.) */
4056 if (!DECL_EXTERNAL (decl))
4057 complete_type (type);
4058 if (!DECL_SIZE (decl)
4059 && TREE_TYPE (decl) != error_mark_node
4060 && (COMPLETE_TYPE_P (type)
4061 || (TREE_CODE (type) == ARRAY_TYPE
4062 && !TYPE_DOMAIN (type)
4063 && COMPLETE_TYPE_P (TREE_TYPE (type)))))
4064 layout_decl (decl, 0);
4065
4066 if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
4067 {
4068 /* An automatic variable with an incomplete type: that is an error.
4069 Don't talk about array types here, since we took care of that
4070 message in grokdeclarator. */
4071 error ("storage size of `%D' isn't known", decl);
4072 TREE_TYPE (decl) = error_mark_node;
4073 }
4074 #if 0
…
4084 #endif
4085
4086 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
4087 && DECL_SIZE (decl) != NULL_TREE
4088 && ! TREE_CONSTANT (DECL_SIZE (decl)))
4089 {
4090 if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
4091 constant_expression_warning (DECL_SIZE (decl));
4092 else
4093 error ("storage size of `%D' isn't constant", decl);
4094 }
4095
4096 if (TREE_STATIC (decl)
4097 && !DECL_ARTIFICIAL (decl)
4098 && current_function_decl
4099 && DECL_CONTEXT (decl) == current_function_decl )
4100 push_local_name (decl);
4101 }
在这里, type 是刚创建的 RECORD_TYPE ,而 decl 是一个非外部声明( non-external declaration )。因此 type 应该已经在这个编译单元中定义,现在可以完成其定义了。
116 tree
117 complete_type (tree type) in typeck.c
118 {
119 if (type == NULL_TREE)
120 /* Rather than crash, we return something sure to cause an error
121 at some point. */
122 return error_mark_node;
123
124 if (type == error_mark_node || COMPLETE_TYPE_P (type))
125 ;
126 else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
127 {
128 tree t = complete_type (TREE_TYPE (type));
129 if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))
130 layout_type (type);
131 TYPE_NEEDS_CONSTRUCTING (type)
132 = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
133 TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
134 = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
135 }
136 else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
137 instantiate_class_template (TYPE_MAIN_VARIANT (type));
138
139 return type;
140 }
对于模板定义,在具现点生成一个新类型。该新类型的定义也在该点完毕(因为其 TREE_SIZE 域是 NULL ,这是一个不完整的类型)。
5274 tree
5275 instantiate_class_template (tree type) in pt.c
5276 {
5277 tree template, args, pattern, t, member;
5278 tree typedecl;
5279 tree pbinfo;
5280
5281 if (type == error_mark_node)
5282 return error_mark_node;
5283
5284 if (TYPE_BEING_DEFINED (type)
5285 || COMPLETE_TYPE_P (type)
5286 || dependent_type_p (type))
5287 return type;
5288
5289 /* Figure out which template is being instantiated. */
5290 template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
5291 my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
5292
5293 /* Figure out which arguments are being used to do the
5294 instantiation. */
5295 args = CLASSTYPE_TI_ARGS (type);
5296
5297 /* Determine what specialization of the original template to
5298 instantiate. */
5299 t = most_specialized_class (template, args);
5300 if (t == error_mark_node)
5301 {
…
5315 }
5316
5317 if (t)
5318 pattern = TREE_TYPE (t);
5319 else
5320 pattern = TREE_TYPE (template);
5321
5322 /* If the template we're instantiating is incomplete, then clearly
5323 there's nothing we can do. */
5324 if (!COMPLETE_TYPE_P (pattern))
5325 return type;
5326
5327 /* If we've recursively instantiated too many templates, stop. */
5328 if (! push_tinst_level (type))
5329 return type;
5330
5331 /* Now we're really doing the instantiation. Mark the type as in
5332 the process of being defined. */
5333 TYPE_BEING_DEFINED (type) = 1;
注意到在上面的 5320 行, pattern 指向最泛化模板所对应的 RECORD_TYPE (也即模板定义中出现的“ SmallObject ”),其 TYPE_SIZE 域在 finish_struct 中被初始化为 bitsize_zero_node 及 size_zero_node 。 5299 行的 most_specialized_class 返回匹配的特化程度最高的定义,找不到或没有特化的定义则返回 NULL 。
虽然在理论上具现的层数是没有限制的,但是在实现中必须防止由于编程或者实现的失误而导致的无限模板具现。这样具现的层数必须是有限制的。在 GCC ,版本 3.4.6 中,全局变量 max_tinst_depth 保存这个限制。其值现在是 500 。
4850 int
4851 push_tinst_level (tree d) in pt.c
4852 {
4853 tree new;
4854
4855 if (tinst_depth >= max_tinst_depth )
4856 {
4857 /* If the instantiation in question still has unbound template parms,
4858 we don't really care if we can't instantiate it, so just return.
4859 This happens with base instantiation for implicit `typename'. */
4860 if (uses_template_parms (d))
4861 return 0;
4862
4863 last_template_error_tick = tinst_level_tick ;
4864 error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",
4865 max_tinst_depth , d);
4866
4867 print_instantiation_context ();
4868
4869 return 0;
4870 }
4871
4872 new = build_expr_wfl (d, input_filename, input_line, 0);
4873 TREE_CHAIN (new) = current_tinst_level ;
4874 current_tinst_level = new;
4875
4876 ++tinst_depth ;
4877 #ifdef GATHER_STATISTICS
4878 if (tinst_depth > depth_reached )
4879 depth_reached = tinst_depth ;
4880 #endif
4881
4882 ++tinst_level_tick ;
4883 return 1;
4884 }
上面在 4872 行,节点 EXPR_WITH_FILE_LOCATION 被构建来记录具现所在的文件及行数。并且这个节点被串接入全局链表 current_tinst_level 用于诊断的目的。
instantiate_class_template (continue)
5335 /* We may be in the middle of deferred access check. Disable
5336 it now. */
5337 push_deferring_access_checks (dk_no_deferred);
5338
5339 push_to_top_level ();
5340
5341 if (t)
5342 {
…
5367 }
5368
5369 SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
5370
5371 /* Set the input location to the template definition. This is needed
5372 if tsubsting causes an error. */
5373 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));
5374
5375 TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
5376 TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
5377 TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
5378 TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
5379 TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
5380 TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
5381 TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
5382 TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
5383 TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
5384 TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
5385 TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
5386 TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
5387 TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
5388 = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (pattern);
5389 TYPE_USES_MULTIPLE_INHERITANCE (type)
5390 = TYPE_USES_MULTIPLE_INHERITANCE (pattern);
5391 TYPE_USES_VIRTUAL_BASECLASSES (type)
5392 = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
5393 TYPE_PACKED (type) = TYPE_PACKED (pattern);
5394 TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
5395 TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
5396 TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
5397 if (ANON_AGGR_TYPE_P (pattern))
5398 SET_ANON_AGGR_TYPE_P (type);
注意上面的 pattern 对应着模板定义中的 RECORD_TYPE ,而 type 对应具现时刻产生的 RECORD_TYPE 。在具现的过程中,我们需要进入具现类型及其子类(如果有子类的话)的作用域,这将改变当前的作用域。因此在第一步,我们需要跑到绑定域的顶层——全局名字空间( 5339 行的 push_to_top_level ),并缓存当前的作用域层次,由下面的 push_scope 及 pushclass 为我们构建合适的上下文(注意这里的 type 及 pattern 的 context 都是“ Loki ”的 NAMESPACE_DECL ——具现的类型被视为在同一作用域下不同的变种)。
instantiate_class_template (continue)
5400 pbinfo = TYPE_BINFO (pattern);
5401
5402 #ifdef ENABLE_CHECKING
5403 if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))
5404 && ! COMPLETE_TYPE_P (TYPE_CONTEXT (type))
5405 && ! TYPE_BEING_DEFINED (TYPE_CONTEXT (type)))
5406 /* We should never instantiate a nested class before its enclosing
5407 class; we need to look up the nested class by name before we can
5408 instantiate it, and that lookup should instantiate the enclosing
5409 class. */
5410 abort ();
5411 #endif
5412
5413 if (BINFO_BASETYPES (pbinfo))
5414 {
5415 tree base_list = NULL_TREE;
5416 tree pbases = BINFO_BASETYPES (pbinfo);
5417 tree paccesses = BINFO_BASEACCESSES (pbinfo);
5418 tree context = TYPE_CONTEXT (type);
5419 bool pop_p;
5420 int i;
5421
5422 /* We must enter the scope containing the type, as that is where
5423 the accessibility of types named in dependent bases are
5424 looked up from. */
5425 pop_p = push_scope (context ? context : global_namespace );
5426
5427 /* Substitute into each of the bases to determine the actual
5428 basetypes. */
5429 for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
5430 {
5431 tree base;
5432 tree access;
5433 tree pbase;
5434
5435 pbase = TREE_VEC_ELT (pbases, i);
5436 access = TREE_VEC_ELT (paccesses, i);
5437
5438 /* Substitute to figure out the base class. */
5439 base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);
5440 if (base == error_mark_node)
5441 continue ;
5442
5443 base_list = tree_cons (access, base, base_list);
5444 TREE_VIA_VIRTUAL (base_list) = TREE_VIA_VIRTUAL (pbase);
5445 }
5446
5447 /* The list is now in reverse order; correct that. */
5448 base_list = nreverse (base_list);
5449
5450 /* Now call xref_basetypes to set up all the base-class
5451 information. */
5452 xref_basetypes (type, base_list);
5453
5454 if (pop_p)
5455 pop_scope (context ? context : global_namespace );
5456 }