GCC-3.4.6源代码学习笔记(126)

5.12.4.2.3.1.1.3.    生成template-id

那么作为结果,对于这个非类型实参,“ chunkSize ”的 IDENTIFIER_NODE 被返回。类似的还有下一个实参“ maxSmallObjectSize ”。因此在 lookup_template_class 4346 行退出 coerce_template_parms 时, arglist 为下图中标记为红色的节点。

点此打开

111 :构建的 arglist

 

lookup_template_class (continue)

 

4352       if (arglist == error_mark_node)

4353         /* We were unable to bind the arguments.  */

4354         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

4355  

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       {

            …

4386       }

4387       if (found)

4388         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);

4389  

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       {

4425         found = xref_tag_from_type (TREE_TYPE (template),

4426                                 DECL_NAME (template),

4427                                 /*globalize=*/ 1);

4428         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);

4429       }

4430        

4431       context = tsubst (DECL_CONTEXT (template), arglist,

4432                     complain, in_decl);

4433       if (!context)

4434         context = global_namespace ;

 

4411 行对于标记为红色的 TREE_VEC uses_template_parms 将依次遍历其成员,任一成员为类型依赖或值依赖都将导致该函数返回非 0 值,使得 is_partial_instantiation 成为 1 同样在 4431 行,变量 template 指向“ SmallObject ”的 TEMPLATE_DECL ,因此其上下文是 Loki NAMESPACE_DECL ,它由 tsubst 返回不作任何处理。

 

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   }

 

变量 template_type 是“ SmallObject ”的 RECORD_TYPE 节点。首先在 4551 行之前,下面红色的节点被构建了。

点此打开

作为具现的实例,要求一个修饰名而不是之前看到的朴素名( plain name )。

 

4002   static tree

4003   classtype_mangled_name (tree t)                                                                     in pt.c

4004   {

4005     if (CLASSTYPE_TEMPLATE_INFO (t)

4006        /* Specializations have already had their names set up in

4007         lookup_template_class.  */

4008       && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))

4009     {

4010       tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));

4011  

4012       /* For non-primary templates, the template parameters are

4013         implicit from their surrounding context.  */

4014       if (PRIMARY_TEMPLATE_P (tmpl))

4015       {

4016         tree name = DECL_NAME (tmpl);

4017         char *mangled_name = mangle_class_name_for_template

4018                            (IDENTIFIER_POINTER (name),

4019                            DECL_INNERMOST_TEMPLATE_PARMS (tmpl),

4020                            CLASSTYPE_TI_ARGS (t));

4021         tree id = get_identifier (mangled_name);

4022         IDENTIFIER_TEMPLATE (id) = name;

4023         return id;

4024       }

4025     }

4026  

4027     return TYPE_IDENTIFIER (t);

4028   }

 

修饰名根据主模板来构建(它通常就是最泛化的模板,通过 most_general_template 来获取),其中主模板的名字是一个标识符(作为比较,一个偏特化的模板的名字是一个 template-id )。以下的宏用于检查指定的模板是否为主模板。

 

2783   #define DECL_PRIMARY_TEMPLATE (NODE) /                                        in cp-tree.h

2784     (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)))

2785  

2786   /* Returns nonzero if NODE is a primary template.  */

27873 #define PRIMARY_TEMPLATE_P (NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))

 

2661   #define DECL_INNERMOST_TEMPLATE_PARMS (NODE) /

2662       INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))

 

INNERMOST_TEMPLATE_P ARMS 只是返回节点 value 域中的内容;而 DECL_TEMPLATE_PARMS 返回 TEMPLATE_DECL arguments 域的指针。

那么具现实例的 TYPE_DECL 被更新为如下的修饰名。

点此打开

112 :内层的 template-id

作为结果, lookup_template_class 返回具现实例所对应的 RECORD_TYPE 节点。接下来,通过其 chain 域(在 finish_template_type 中的 TYPE_STUB_DECL )把 TYPE_DECL (粗红线节点)作为 template-id 返回。

5.12.4.2.3.1.2.          外层 template-id

对于外层的 template-id ,内层 template-id ——“ SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> ”是其一个实参;而且下面的 arguments 是一个具有单个成员为该 template-id tree_vec 。然后我们又以下面的代码进行解析。

 

cp_parser_template_id

 

7991     /* Build a representation of the specialization.  */

7992     if (TREE_CODE (template) == IDENTIFIER_NODE)

7993       template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);

7994     else if (DECL_CLASS_TEMPLATE_P (template)

7995           || DECL_TEMPLATE_TEMPLATE_PARM_P (template))

7996       template_id

7997         = finish_template_type (template, arguments,

7998                            cp_lexer_next_token_is (parser->lexer,

7999                                                 CPP_SCOPE));

 

不过在 lookup_template_class 中的处理有一些不同,因为“ ThreadingModel ”是模板参数。

 

4133   tree

4134   lookup_template_class (tree d1,                                                                              in pt.c

4135                       tree arglist,

4136                       tree in_decl,

4137                       tree context,

4138                       int entering_scope,

4139                       tsubst_flags_t complain)

4140   {

4141     tree template = NULL_TREE, parmlist;

4142     tree t;

4143    

4144     timevar_push (TV_NAME_LOOKUP);

4145    

4146     if (TREE_CODE (d1) == IDENTIFIER_NODE)

4147     {

4148       if (IDENTIFIER_VALUE (d1)

4149           && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))

4150         template = IDENTIFIER_VALUE (d1);

4151       else

4152       {

4153           if (context)

4154             push_decl_namespace (context);

4155          template = lookup_name (d1, /*prefer_type=*/ 0);

4156           template = maybe_get_template_decl_from_type_decl (template);

4157           if (context)

4158             pop_decl_namespace ();

4159       }

4160       if (template)

4161         context = DECL_CONTEXT (template);

4162     }

4163     else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))

4164     {

4165       tree type = TREE_TYPE (d1);

4166  

4167       /* If we are declaring a constructor, say A<T>::A<T>, we will get

4168         an implicit typename for the second A. Deal with it.  */

4169       if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))

4170       type = TREE_TYPE (type);

4171       

4172         if (CLASSTYPE_TEMPLATE_INFO (type))

4173       {

4174          template = CLASSTYPE_TI_TEMPLATE (type);

4175          d1 = DECL_NAME (template);

4176       } 

4177     }

4178     else if (TREE_CODE (d1) == ENUMERAL_TYPE

4179           || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))

4180     {

4181       template = TYPE_TI_TEMPLATE (d1);

4182       d1 = DECL_NAME (template);

4183     }

4184     else if (TREE_CODE (d1) == TEMPLATE_DECL

4185           && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)

4186     {

4187       template = d1;

4188       d1 = DECL_NAME (template);

4189       context = DECL_CONTEXT (template);

4190     }

4191  

4192     /* With something like `template <class T> class X class X { ... };'

4193       we could end up with D1 having nothing but an IDENTIFIER_VALUE.

4194       We don't want to do that, but we have to deal with the situation,

4195       so let's give them some syntax errors to chew on instead of a

4196       crash. Alternatively D1 might not be a template type at all.  */

4197     if (! template)

4198     {

4199       if (complain & tf_error)

4200         error ("`%T' is not a template", d1);

4201       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

4202     }

4203  

4204     if (TREE_CODE (template) != TEMPLATE_DECL

4205        /* Make sure it's a user visible template, if it was named by

4206          the user.  */

4207        || ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)

4208           && !PRIMARY_TEMPLATE_P (template)))

4209     {

4210       if (complain & tf_error)

4211       {

4212         error ("non-template type `%T' used as a template", d1);

4213         if (in_decl)

4214           cp_error_at ("for template declaration `%D'", in_decl);

4215       }

4216       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

4217     }

4218  

4219     complain &= ~tf_user;

4220    

4221     if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))

4222     {

4223       /* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store

4224         template arguments */

4225  

4226       tree parm;

4227       tree arglist2;

4228  

4229       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);

4230  

4231       /* Consider an example where a template template parameter declared as

4232  

4233         template <class T, class U = std::allocator<T> > class TT

4234  

4235         The template parameter level of T and U are one level larger than

4236         of TT. To proper process the default argument of U, say when an

4237         instantiation `TT<int>' is seen, we need to build the full

4238         arguments containing {int} as the innermost level. Outer levels,

4239         available when not appearing as default template argument, can be

4240         obtained from `current_template_args ()'.

4241  

4242         Suppose that TT is later substituted with std::vector. The above

4243         instantiation is `TT<int, std::allocator<T> >' with TT at

4244         level 1, and T at level 2, while the template arguments at level 1

4245         becomes {std::vector} and the inner level 2 is {int}.  */

4246  

4247       if (current_template_parms )

4248         arglist = add_to_template_args (current_template_args (), arglist);

4249  

4250       arglist2 = coerce_template_parms (parmlist, arglist, template,

4251                                   complain, /*require_all_args=*/ 1);

4252       if (arglist2 == error_mark_node

4253          || (!uses_template_parms (arglist2)

4254             && check_instantiated_args (template, arglist2, complain)))

4255         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

4256  

4257       parm = bind_template_template_parm (TREE_TYPE (template), arglist2);

4258       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);

4259     }

        …

4574   }

 

上面的 d1 指向下图的 TEMPLATE_DECL 。而 arglist 指向代表内层 template-id 的子树。

点此打开

还有注意 current_template_parms 指向的节点,它是“ SmallObject ”的实参。它还应该是“ ThreadingModel ”的实参,因为“ ThreadingModel ”被包括在“ SmallObject ”的参数列表中。因此在 4248 行,函数 current_template_args 拷贝出这个向量,不过拷贝节点的 type 域是空的。

 

511     static tree

512    add_to_template_args (tree args, tree extra_args)                                              in pt.c

513    {

514      tree new_args;

515      int extra_depth;

516      int i;

517      int j;

518   

519      extra_depth = TMPL_ARGS_DEPTH (extra_args);

520      new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth);

521   

522      for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)

523        SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i));

524   

525      for (j = 1; j <= extra_depth; ++j, ++i)

526        SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));

527       

528      return new_args;

529    }

 

接着在 4248 行,构建了 TREE_VEC 类型的 arglists ,其第一个成员指向上图中红色的 TREE_VEC ,而第二个成员指向内层 template-id (在下面传递给 args )的 TREE_VEC 。那么在 4250 行的 parmlist (在下面传递给 parms )指向图 112 中的其他 TREE_VEC ,这个节点代表“ ThreadingModel ”的实参。

 

3805   static tree

3806   coerce_template_parms (tree parms,                                                                       in pt.c

3807                       tree args,

3808                       tree in_decl,

3809                       tsubst_flags_t complain,

3810                       int require_all_arguments)

3811   {

3812     int nparms, nargs, i, lost = 0;

3813     tree inner_args;

3814     tree new_args;

3815     tree new_inner_args;

3816  

3817     inner_args = INNERMOST_TEMPLATE_ARGS (args);

3818     nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;

3819     nparms = TREE_VEC_LENGTH (parms);

3820  

3821     if (nargs > nparms

3822        || (nargs < nparms

3823          && require_all_arguments

3824          && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))

3825     {

3826       if (complain & tf_error)

3827       {

3828         error ("wrong number of template arguments (%d, should be %d)",

3829              nargs, nparms);

3830         

3831         if (in_decl)

3832           cp_error_at ("provided for `%D'", in_decl);

3833       }

3834  

3835       return error_mark_node;

3836     }

3837  

3838     new_inner_args = make_tree_vec (nparms);

3839     new_args = add_outermost_template_args (args, new_inner_args);

 

3817 行, INNERMOST_TEMPLATE_ARGS 返回先前所构建的 arglists 的最后一个成员,这是代表内层 template-id 的节点。作为结果,我们得到 nparms 1 ), nargs 1 )。

 

538    static tree

539    add_outermost_template_args (tree args, tree extra_args)                                          in pt.c

540    {

541      tree new_args;

542   

543      /* If there are more levels of EXTRA_ARGS than there are ARGS,

544        something very fishy is going on.  */

545      my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),

546                       0);

547   

548      /* If *all* the new arguments will be the EXTRA_ARGS, just return

549        them.  */

550      if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))

551        return extra_args;

552   

553      /* For the moment, we make ARGS look like it contains fewer levels.  */

554      TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);

555     

556      new_args = add_to_template_args (args, extra_args);

557   

558      /* Now, we restore ARGS to its full dimensions.  */

559      TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);

560   

561      return new_args;

562    }

 

因为 args 是包含 TREE_VEC TREE_VEC TMPL_ARGS_DEPTH 返回的外层向量的长度(它是 2 ), extra_args 是长度是 1 TREE_VEC ,因为不是包含 TREE_VEC TREE_VEC TMPL_ARGS_DEPTH 对其总是返回 1 。因此 add_outermost_template_args 的总体效果是使用 extra_args 来替代 args 的最后的成员。

 

coerce_template_parms (continue)

 

3840     for (i = 0; i < nparms; i++)

3841     {

3842       tree arg;

3843       tree parm;

3844  

3845       /* Get the Ith template parameter.  */

3846       parm = TREE_VEC_ELT (parms, i);

3847  

3848       /* Calculate the Ith argument.  */

3849       if (i < nargs)

3850         arg = TREE_VEC_ELT (inner_args, i);

3851       else if (require_all_arguments)

3852         /* There must be a default arg in this case.  */

3853         arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,

3854                               complain, in_decl);

3855       else

3856         break ;

3857        

3858       my_friendly_assert (arg, 20030727);

3859       if (arg == error_mark_node)

3860         error ("template argument %d is invalid", i + 1);

3861       else

3862         arg = convert_template_argument (TREE_VALUE (parm),

3863                                      arg, new_args, complain, i,

3864                                     i n_decl);

3865        

3866       if (arg == error_mark_node)

3867         lost++;

3868       TREE_VEC_ELT (new_inner_args, i) = arg;

3869     }

3870  

3871     if (lost)

3872       return error_mark_node;

3873  

3874     return new_inner_args;

3875   }

 

在这个函数的调用中,参数 parm 是上图(不是图 112 )中的 TYPE_DECL arg 是内层 template-id (它是 TYPE_DECL 节点); args 是由 add_outermost_template_args 构建的包含 TREE_VEC TREE_VEC

 

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);

3649  

3650     if (TREE_CODE (arg) == TREE_LIST

3651         && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)

3652     { 

          …

3660     }

3661  

3662     requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;

3663     requires_type = (TREE_CODE (parm) == TYPE_DECL

3664                   || requires_tmpl_type);

3665  

3666     is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL

3667                   && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)

3668                  || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM

3669                  || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);

3670    

3671     if (is_tmpl_type

3672        && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM

3673            || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))

3674       arg = TYPE_STUB_DECL (arg);

3675  

3676     is_type = TYPE_P (arg) || is_tmpl_type;

        …

3722     if (is_type)

3723     {

3724       if (requires_tmpl_type)

3725       {

            …

3759       }

3760       else

3761         val = groktypename (arg);

3762     }

3763     else

3764     {

         

3790     }

3791  

3792     return val;

3793   }

 

因为 arg 是一个 TYPE_DECL 节点,在 3761 行, groktypename 不对它做任何事,只是返回它。然后在 3868 行,在 coerce_template_parms 中该节点被填入 new_inner_args 。记得当构建 new_inner_args 时,这个节点被刻意忽略了,但现在我们开始照顾到它了。因此从 4250 行返回到 lookup_template_class 时, arglist2 arglist 相同。

记住在 4257 行的 template 指向代表“ ThreadingModel ”的 TEMPLATE_DECL 。接下来,将构建 BOUND_TEMPLATE_TEMPLATE_PARM 节点,正如其名字所暗示,它代表模板模板参数的一个绑定。

 

995    tree

996    bind_template_template_parm (tree t, tree newargs)                                                  in tree.c

997    {

998      tree decl = TYPE_NAME (t);

999      tree t2;

1000  

1001     t2 = make_aggr_type (BOUND_TEMPLATE_TEMPLATE_PARM);

1002     decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);

1003  

1004     /* These nodes have to be created to reflect new TYPE_DECL and template

1005       arguments.  */

1006     TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));

1007     TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;

1008     TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)

1009        = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),

1010                   newargs, NULL_TREE);

1011  

1012     TREE_TYPE (decl) = t2;

1013     TYPE_NAME (t2) = decl;

1014     TYPE_STUB_DECL (t2) = decl;

1015     TYPE_SIZE (t2) = 0;

1016  

1017     return t2;

1018   }

 

最终,所构建的 BOUND_TEMPLATE_TEMPLATE_PARM 节点如下图所示。并且它被 lookup_template_class 返回。

点此打开

113 BOUND_TEMPLATE_TEMPLATE_PARM 节点

那么在 finish_template_type cp_parser_template_id 中,通过该节点的 chain 域得到的 TYPE_DECL 被返回作为该 template-id 的代表。

接着该节点为 cp_parser_class_name 返回给 cp_parser_base_specifier 。相关代码参照章节 完成类名查找

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值