5.12.5.2.2.2.1.1.2. 替换剩下的缺省实参
第二个参数是下图中由红色箭头指向的节点。因为第三个参数是类似的,在下面我们跳过它。
( 点此打开 )
那么在 coerce_template_parms 的 3835 行,当调用 tsubst_template_arg 时,被上面第二个参数的 purpose 域所引用的 tree_list 节点,被作为第一个实参传入。在 tsubst_template_arg 中,接着调用 tsubst_expr ,该函数为非语句( non-statement )调用 tsubst_copy_and_build 。然后在 tsubst_copy_and_build 中,调用 tsubst_copy ,并返回保存在 purpose 域的 INTEGER_CST 节点。而该节点被一直返回到 tsubst_template_arg 。
接着 convert_template_argument 被调用来产生合适的实参。在这里 parm 是由 value 域所指向的节点,而 arg 是被上图中红色箭头所指向的 tree_list 节点的 purpose 域。
3636 static tree
3637 convert_template_argument (tree parm, in pt.c
3638 tree arg,
3639 tree args,
3640 tsubst_flags_t complain,
3641 int i,
3642 tree in_decl)
3643 {
3644 tree val;
3645 tree inner_args;
3646 int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
3647
3648 inner_args = INNERMOST_TEMPLATE_ARGS (args);
…
3722 if (is_type)
3723 {
…
3762 }
3763 else
3764 {
3765 tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
3766
3767 if (invalid_nontype_parm_type_p (t, complain))
3768 return error_mark_node;
3769
3770 if (!uses_template_parms (arg) && !uses_template_parms (t))
3771 /* We used to call digest_init here. However, digest_init
3772 will report errors, which we don't want when complain
3773 is zero. More importantly, digest_init will try too
3774 hard to convert things: for example, `0' should not be
3775 converted to pointer type at this point according to
3776 the standard. Accepting this is not merely an
3777 extension, since deciding whether or not these
3778 conversions can occur is part of determining which
3779 function template to call, or whether a given explicit
3780 argument specification is valid. */
3781 val = convert_nontype_argument (t, arg);
3782 else
3783 val = arg;
3784
3785 if (val == NULL_TREE)
3786 val = error_mark_node;
3787 else if (val == error_mark_node && (complain & tf_error))
3788 error ("could not convert template argument `%E' to `%T'",
3789 arg, t);
3790 }
3791
3792 return val;
3793 }
parm 的类型( TREE_TYPE )是 INTEGER_TYPE ,它由 tsubst 返回不作任何处理,并且因为 arg 指向 INTEGER_CST 节点,在 3781 行的 convert_nontype_argument 不能对 arg 做更多的简化。 So as last we just get the node pointed by arg as the final argument.
5.12.5.2.2.2.1.1.3. 生成节点
下面的 template_type 指向“ SmallObject ”的 RECORD_TYPE 节点,而 arglist 是下面的 tree_vec (忽略了第三个实参)。
( 点此打开 )
lookup_template_class (continue)
4356 /* In the scope of a template class, explicit references to the
4357 template class refer to the type of the template, not any
4358 instantiation of it. For example, in:
4359
4360 template <class T> class C { void f(C<T>); }
4361
4362 the `C<T>' is just the same as `C'. Outside of the
4363 class, however, such a reference is an instantiation. */
4364 if (comp_template_args (TYPE_TI_ARGS (template_type),
4365 arglist))
4366 {
4367 found = template_type;
4368
4369 if (!entering_scope && PRIMARY_TEMPLATE_P (template))
4370 {
4371 tree ctx;
4372
4373 for (ctx = current_class_type ;
4374 ctx && TREE_CODE (ctx) != NAMESPACE_DECL;
4375 ctx = (TYPE_P (ctx)
4376 ? TYPE_CONTEXT (ctx)
4377 : DECL_CONTEXT (ctx)))
4378 if (TYPE_P (ctx) && same_type_p (ctx, template_type))
4379 goto found_ctx;
4380
4381 /* We're not in the scope of the class, so the
4382 TEMPLATE_TYPE is not the type we want after all. */
4383 found = NULL_TREE;
4384 found_ctx:;
4385 }
4386 }
4387 if (found)
4388 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
上面的注释清楚地解释了上面代码的目的。对于注释中给出的例子,方法 f 一样被构建入 TEMPLATE_DECL ,但是因为它是模板类的方法,其参数列表由 current_template_args 生成。而 f 的参数“ C<T> ”是一个 template-id 。毫无疑问,其实参列表“ T ”与其封闭模板类的参数列表相同。
首先 comp_template_args 确保这两个列表是相同的。接着在 4369 行的 entering_scope 仅当我们将要进入所要查找类的作用域时,为非 0 值(那么处理 f 时,其为 0 )。因此在 4373 行的 FOR 块验证 template_type 是否为封闭类。如果是,它就是我们所期待的类型。
3899 int
3900 comp_template_args (tree oldargs, tree newargs) in pt.c
3901 {
3902 int ;
3903
3904 if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
3905 return 0;
3906
3907 for (i = 0; i < TREE_VEC_LENGTH (oldargs); ++i)
3908 {
3909 tree nt = TREE_VEC_ELT (newargs, i);
3910 tree ot = TREE_VEC_ELT (oldargs, i);
3911
3912 if (! template_args_equal (ot, nt))
3913 return 0;
3914 }
3915 return 1;
3916 }
检查模板参数的相同性与检查树节点相同性的方法一致。
3879 static int
3880 template_args_equal (tree ot, tree nt) in pt.c
3881 {
3882 if (nt == ot)
3883 return 1;
3884
3885 if (TREE_CODE (nt) == TREE_VEC)
3886 /* For member templates */
3887 return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
3888 else if (TYPE_P (nt))
3889 return TYPE_P (ot) && same_type_p (ot, nt);
3890 else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
3891 return 0;
3892 else
3893 return cp_tree_equal (ot, nt);
3894 }
上面的代码处理非具现的情形,在 4388 行的 return 语句结束。那么对于具现的情形,首先需要检查类似的具现已经处理了(一旦处理完,它就被记录在 DECL_TEMPLATE_INSTANTIATIONS 指向的链表中)。
lookup_template_class (continue)
4390 for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
4391 *tp;
4392 tp = &TREE_CHAIN (*tp))
4393 if (comp_template_args (TREE_PURPOSE (*tp), arglist))
4394 {
…
4405 }
4406
4407 /* This type is a "partial instantiation" if any of the template
4408 arguments still involve template parameters. Note that we set
4409 IS_PARTIAL_INSTANTIATION for partial specializations as
4410 well. */
4411 is_partial_instantiation = uses_template_parms (arglist);
4412
4413 /* If the deduced arguments are invalid, then the binding
4414 failed. */
4415 if (!is_partial_instantiation
4416 && check_instantiated_args (template,
4417 INNERMOST_TEMPLATE_ARGS (arglist),
4418 complain))
4419 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
4420
4421 if (!is_partial_instantiation
4422 && !PRIMARY_TEMPLATE_P (template)
4423 && TREE_CODE (CP_DECL_CONTEXT (template)) == NAMESPACE_DECL)
4424 {
…
4429 }
4430
4431 context = tsubst (DECL_CONTEXT (template), arglist,
4432 complain, in_decl);
4433 if (!context)
4434 context = global_namespace ;
在 4412 行, uses_template_args 返回 0 来表示一个模板具现。在具现时刻,对于类型参数,它必须不能是可变大小的,比如语句:
struct S { int i[f()]; }
在 GNU C 中是有效的。而对于非类型参数,它必须是一个整形或枚举型常量。这个条件由 check_instantiated_args 来验证。
8705 static bool
8706 check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain) in pt.c
8707 {
8708 int ix, len = DECL_NTPARMS (tmpl);
8709 bool result = false;
8710
8711 for (ix = 0; ix != len; ix++)
8712 {
8713 tree t = TREE_VEC_ELT (args, ix);
8714
8715 if (TYPE_P (t))
8716 {
8717 /* [basic.link]: A name with no linkage (notably, the name
8718 of a class or enumeration declared in a local scope)
8719 shall not be used to declare an entity with linkage.
8720 This implies that names with no linkage cannot be used as
8721 template arguments. */
8722 tree nt = no_linkage_check (t);
8723
8724 if (nt)
8725 {
8726 if (!(complain & tf_error))
8727 /*OK*/;
8728 else if (TYPE_ANONYMOUS_P (nt))
8729 error ("`%T' uses anonymous type", t);
8730 else
8731 error ("`%T' uses local type `%T'", t, nt);
8732 result = true;
8733 }
8734 /* In order to avoid all sorts of complications, we do not
8735 allow variably-modified types as template arguments. */
8736 else if (variably_modified_type_p (t))
8737 {
8738 if (complain & tf_error)
8739 error ("`%T' is a variably modified type", t);
8740 result = true;
8741 }
8742 }
8743 /* A non-type argument of integral or enumerated type must be a
8744 constant. */
8745 else if (TREE_TYPE (t)
8746 && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
8747 && !TREE_CONSTANT (t))
8748 {
8749 if (complain & tf_error)
8750 error ("integral expression `%E' is not constant", t);
8751 result = true;
8752 }
8753 }
8754 if (result && complain & tf_error)
8755 error (" trying to instantiate `%D'", tmpl);
8756 return result;
8757 }
在 8722 行,如果类型依赖于一个不具有链接性类型, no_linkage_check 返回它;否则返回 NULL 。而对于这样的类型,它不能被用作模板具现的实参。一个类型是否具有可变大小则由下面的 variably_modified_type_p 来检查。
4316 bool
4317 variably_modified_type_p (tree type) in tree.c
4318 {
4319 tree t;
4320
4321 if (type == error_mark_node)
4322 return false;
4323
4324 /* If TYPE itself has variable size, it is variably modified.
4325
4326 We do not yet have a representation of the C99 '[*]' syntax.
4327 When a representation is chosen, this function should be modified
4328 to test for that case as well. */
4329 t = TYPE_SIZE (type);
4330 if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
4331 return true;
4332
4333 switch (TREE_CODE (type))
4334 {
4335 case POINTER_TYPE:
4336 case REFERENCE_TYPE:
4337 case ARRAY_TYPE:
4338 /* If TYPE is a pointer or reference, it is variably modified if
4339 the type pointed to is variably modified. Similarly for arrays;
4340 note that VLAs are handled by the TYPE_SIZE check above. */
4341 return variably_modified_type_p (TREE_TYPE (type));
4342
4343 case FUNCTION_TYPE:
4344 case METHOD_TYPE:
4345 /* If TYPE is a function type, it is variably modified if any of the
4346 parameters or the return type are variably modified. */
4347 {
4348 tree parm;
4349
4350 if (variably_modified_type_p (TREE_TYPE (type)))
4351 return true;
4352 for (parm = TYPE_ARG_TYPES (type);
4353 parm && parm != void_list_node;
4354 parm = TREE_CHAIN (parm))
4355 if (variably_modified_type_p (TREE_VALUE (parm)))
4356 return true;
4357 }
4358 break ;
4359
4360 case INTEGER_TYPE:
4361 /* Scalar types are variably modified if their end points
4362 aren't constant. */
4363 t = TYPE_MIN_VALUE (type);
4364 if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
4365 return true;
4366 t = TYPE_MAX_VALUE (type);
4367 if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
4368 return true;
4369 return false;
4370
4371 default :
4372 break ;
4373 }
4374
4375 /* The current language may have other cases to check, but in general,
4376 all other types are not variably modified. */
4377 return (*lang_hooks .tree_inlining.var_mod_type_p ) (type);
4378 }
一个类型是否可变大小由其 TYPE_SIZE 域显示。如果这个域里的是一个 INTEGER_CST ,就是大小不可变的。因此对于可能包含可变大小的类型,它需要被一级一级地查找。对于 C++ 语言,方法是需要额外考虑的类型, 4377 行的钩子 var_mod_type_p 覆盖了这个情形。而它调用了下面的 cp_var_mod_type_p 。
381 static bool
382 cp_var_mod_type_p (tree type) in cp-lang.c
383 {
384 /* If TYPE is a pointer-to-member, it is variably modified if either
385 the class or the member are variably modified. */
386 if (TYPE_PTR_TO_MEMBER_P (type))
387 return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
388 || variably_modified_type_p(TYPE_PTRMEM_POINTED_TO_TYPE (type)));
389
390 /* All other types are not variably modified. */
391 return false;
392 }
对于我们的模板具现实参,它们成功地通过了这个测试。
在 4431 和, template 指向“ SmallObject ”的 TEMPLATE_DECL ,它被包含在名字空间“ Loki ”中。因此在 4431 行的 tsubst 只是返回对应的 NAMESPACE_DECL 而不做处理。
lookup_template_class (continue)
4436 /* Create the type. */
4437 if (TREE_CODE (template_type) == ENUMERAL_TYPE)
4438 {
…
4450 }
4451 else
4452 {
4453 t = make_aggr_type (TREE_CODE (template_type));
4454 CLASSTYPE_DECLARED_CLASS (t)
4455 = CLASSTYPE_DECLARED_CLASS (template_type);
4456 SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
4457 TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
4458
4459 /* A local class. Make sure the decl gets registered properly. */
4460 if (context == current_function_decl )
4461 pushtag (DECL_NAME (template), t, 0);
4462 }
4463
4464 /* If we called start_enum or pushtag above, this information
4465 will already be set up. */
4466 if (!TYPE_NAME (t))
4467 {
4468 TYPE_CONTEXT (t) = FROB_CONTEXT (context);
4469
4470 type_decl = create_implicit_typedef (DECL_NAME (template), t);
4471 DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
4472 TYPE_STUB_DECL (t) = type_decl;
4473 DECL_SOURCE_LOCATION (type_decl)
4474 = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
4475 }
4476 else
4477 type_decl = TYPE_NAME (t);
4478
4479 TREE_PRIVATE (type_decl)
4480 = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
4481 TREE_PROTECTED (type_decl)
4482 = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
4483
4484 /* Set up the template information. We have to figure out which
4485 template is the immediate parent if this is a full
4486 instantiation. */
4487 if (parm_depth == 1 || is_partial_instantiation
4488 || !PRIMARY_TEMPLATE_P (template))
4489 /* This case is easy; there are no member templates involved. */
4490 found = template;
4491 else
4492 {
…
4544 }
4545
4546 SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
4547 DECL_TEMPLATE_INSTANTIATIONS (template)
4548 = tree_cons (arglist, t,
4549 DECL_TEMPLATE_INSTANTIATIONS (template));
4550
4551 if (TREE_CODE (t) == ENUMERAL_TYPE
4552 && !is_partial_instantiation)
4553 /* Now that the type has been registered on the instantiations
4554 list, we set up the enumerators. Because the enumeration
4555 constants may involve the enumeration type itself, we make
4556 sure to register the type first, and then create the
4557 constants. That way, doing tsubst_expr for the enumeration
4558 constants won't result in recursive calls here; we'll find
4559 the instantiation and exit above. */
4560 tsubst_enum (template_type, t, arglist);
4561
4562 /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
4563 is set up. */
4564 if (TREE_CODE (t) != ENUMERAL_TYPE)
4565 DECL_NAME (type_decl) = classtype_mangled_name (t);
4566 if (is_partial_instantiation)
4567 /* If the type makes use of template parameters, the
4568 code that generates debugging information will crash. */
4569 DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
4570
4571 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
4572 }
4573 timevar_pop (TV_NAME_LOOKUP);
4574 }
对于新的具现(例如我们的例子),一个 RECORD_TYPE 及关联的节点被构建,因为每次具现都引入一个新的类型。为了防止重复定义,每个具现都被 4247 行的 DECL_TEMPLATE_INSTANTIATIONS 所记录;不过这只在同一个编译单元中可用。这种方式不能避免跨编译单元的重复定义,但是链接器可以有所帮助。在函数的退出点,我们得到以下的中间树(新节点以蓝色显示)。
( 点此打开 )
上图中的 RECORD_TYPE 节点是由 lookup_template_class 返回的,而通过其 chain 域访问的 TYPE_DECL 则由 finish_template_type 返回。这个 TYPE_DECL 被 cp_parser_template_id 在 7997 行用作 template_id 的结果,然后在下面 cp_parser_class_name 中返回作 decl 。
cp_parser_class_name (continue)
11812 decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
11813
11814 /* If this is a typename, create a TYPENAME_TYPE. */
11815 if (typename_p && decl != error_mark_node)
11816 {
11817 decl = make_typename_type (scope, decl, /*complain=*/ 1);
11818 if (decl != error_mark_node)
11819 decl = TYPE_NAME (decl);
11820 }
11821
11822 /* Check to see that it is really the name of a class. */
11823 if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
11824 && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
11825 && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
11826 /* Situations like this:
11827
11828 template <typename T> struct A {
11829 typename T::template X<int>::I i;
11830 };
11831
11832 are problematic. Is `T::template X<int>' a class-name? The
11833 standard does not seem to be definitive, but there is no other
11834 valid interpretation of the following `::'. Therefore, those
11835 names are considered class-names. */
11836 decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
11837 else if (decl == error_mark_node
11838 || TREE_CODE (decl) != TYPE_DECL
11839 || !IS_AGGR_TYPE (TREE_TYPE (decl)))
11840 {
11841 cp_parser_error (parser, "expected class-name");
11842 return error_mark_node;
11843 }
11844
11845 return decl;
11846 }
在 11812 行, cp_parser_maybe_treat_template_as_class 不对传入 TYPE_DECL 做任何事,只是返回对应的 TYPE_DECL ,如果它是 TEMPALTE_DECL 。因此 decl 也被 cp_parser_class_name 返回。事实上这个 TYPE_DECL 正是我们在 decl-specifier-seq 中查找的 type-specifier 。这个节点一直返回到 cp_parser_simple_declaration 。