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

5.12.5.2.2.2.1.3.1.            具现基类 实参替换

基类可能依赖于模板参数,就像这里我们的例子那样。因此要具现派生类,首先需要正确地具现其基类。在这里我们为了方便起见,在下面重新显示了“ SmallObject ”部分的中间树。“ SmallObject ”具有单个基类——“ ThreadingModel ”,其缺省类型是“ SingleThreaded ”,而且“ SmallObject ”声明在名字空间“ Loki ”中。

(点此打开 )

115 :“ SmallObject 部分的中间树

instantiate_class_template 中的 5320 pattern 是图中上部的 RECORD_TYPE 节点 而在 5400 行的 pinfo pattern binfo 域所指向。那么在 5425 行,名字空间“ Loki ”成为了当前的作用域。因此在 5439 行,调用 tsubst 的第一个实参是节点 BOUND_TEMPLATE_TEMPLATE_PARM 而第二个实参 args 是下图中红色的 tree_vec 节点。

点此打开

116 VAR_DECL 部分的中间树

 

6681   static tree

6682   tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

6685  

6686     if (t == NULL_TREE || t == error_mark_node

6687         || t == integer_type_node

6688         || t == void_type_node

6689         || t == char_type_node

6690         || t == unknown_type_node

6691         || TREE_CODE (t) == NAMESPACE_DECL)

6692       return t;

6693  

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

6698  

6699     my_friendly_assert (type != unknown_type_node, 20030716);

6700  

6701     if (type && TREE_CODE (t) != FUNCTION_DECL

6702         && TREE_CODE (t) != TYPENAME_TYPE

6703         && TREE_CODE (t) != TEMPLATE_DECL

6704         && TREE_CODE (t) != IDENTIFIER_NODE

6705         && TREE_CODE (t) != FUNCTION_TYPE

6706         && TREE_CODE (t) != METHOD_TYPE)

6707       type = tsubst (type, args, complain, in_decl);

6708     if (type == error_mark_node)

6709       return error_mark_node;

6710  

6711     if (DECL_P (t))

6712       return tsubst_decl (t, args, type, complain);

6713  

6714     switch (TREE_CODE (t))

6715     {

          …

6776       case TEMPLATE_TYPE_PARM:

6777       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785         r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6790         {

6791           idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795         {

6796           idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802           tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             return error_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

6812             if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)

6813             {

6814                my_friendly_assert (TYPE_P (arg), 0);

6815               return cp_build_qualified_type_real

6816                       (arg, cp_type_quals (arg) | cp_type_quals (t),

6817                        complain | tf_ignore_bad_quals);

6818             }

6819              else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6820             {

6821               /* We are processing a type constructed from

6822                 a template template parameter.  */

6823               tree argvec = tsubst (TYPE_TI_ARGS (t),

6824                                args, complain, in_decl);

6825               if (argvec == error_mark_node)

6826                 return error_mark_node;

 

因为 t 指向节点 BOUND_TEMPLATE_TEMPALTE_PARM ,在 6791 idx 0 ,而 level 1 ;然后在 6806 行, arg 指向“ SingleThreaded ”对应的 TEMPLATE_DECL 节点。注意到在 6823 行,对于我们的例子, tsubst 的第一个实参“ TYPE_TI_ARGS (t) ”参考本节中第一个图中的包含 2 个元素的 tree_vec 节点【其定义为: (TI_ARGS (TYPE_TEMPLATE_INFO (NODE))) 】。

 

6681   static tree

6682   tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

         ...

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

        …

6714     switch (TREE_CODE (t))

6715     {

          …

6950      case TREE_VEC:

6951        if (type != NULL_TREE)

6952        {

              …

6970        }

6971

6972        /* Otherwise, a vector of template arguments.  */

6973        return tsubst_template_args (t, args, complain, in_decl);

           …

7304     }

7305 }

 

这里实参 t 代表模板的参数,而 args 代表具现时的实参。对于模板,因为语义检查( semantic check )应该在具现点进行, tsubst_template_args 会验证实参是否与参数相符。现在 t 指向如下的红色节点。

t1

5744   static tree

5745   tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)              in pt.c

5746   {

5747     int len = TREE_VEC_LENGTH (t);

5748     int need_new = 0, i;

5749     tree *elts = alloca (len * sizeof (tree));

5750    

5751     for (i = 0; i < len; i++)

5752     {

5753       tree orig_arg = TREE_VEC_ELT (t, i);

5754       tree new_arg;

5756  

5757       if (TREE_CODE (orig_arg) == TREE_VEC)

5758         new_arg = tsubst_template_args (orig_arg, args, complain, in_decl);

5759       else

5760         new_arg = tsubst_template_arg (orig_arg, args, complain, in_decl);

5761        

5762       if (new_arg == error_mark_node)

5763         return error_mark_node;

5764  

5765       elts[i] = new_arg;

5766       if (new_arg != orig_arg)

5767         need_new = 1;

5768     }

5769    

5770     if (!need_new)

5771       return t;

5772  

5773     t = make_tree_vec (len);

5774     for (i = 0; i < len; i++)

5775       TREE_VEC_ELT (t, i) = elts[i];

5776    

5777     return t;

5778   }

 

看到在 t 中的第一个元素是一个 tree_vec ,它是外层模板的参数。这个 tree_vec (第一个元素)及作为内层模板参数的第二个元素, 都由 tsubst_template_arg 来处理。在这个函数在,对于所有的候选者, TYPE_P 返回 0 因为它们都不是代表类型的节点。看到在调用 tsubst_expr 时参数 t args 与调用 tsubst_template_arg 时相同。

 

7822   static tree

7823   tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)                            in pt.c

7824   {

7825     tree stmt, tmp;

7826     tsubst_flags_t stmt_expr

7827       = complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body);

7828  

7829     complain ^= stmt_expr;

7830     if (t == NULL_TREE || t == error_mark_node)

7831       return t;

7832  

7833     if (!STATEMENT_CODE_P (TREE_CODE (t)))

7834       return tsubst_copy_and_build (t, args, complain, in_decl,

7835                                /*function_p=*/ false);

        …

8156   }

 

这里所有的模板实参都不是语句( statement )因此都是调用 tsubst_copy_and_build

 

8179   tree

8180   tsubst_copy_and_build (tree t,                                                                         in pt.c

8181                     tree args,

8182                     tsubst_flags_t complain,

8183                     tree in_decl,

8184                      bool function_p)

8185   {

8186     #define RECUR(NODE) /

8187     tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/ false)

8188

8189     tree op1;

8190

8191     if (t == NULL_TREE || t == error_mark_node)

8192      return t;

8193  

8194     switch (TREE_CODE (t))

8195     {

         …

8693       default :

8694         return tsubst_copy (t, args, complain, in_decl);

8695     }

8696

8697   #undef RECUR

8698   }

 

对于外层模板参数,第一个是 TEMPLATE_TEMPALTE_PARM ,第二及第三都是 TEMPLATE_PARM_INDEX ;而内层模板的参数是 TEMPLATE_TYPE_PARM 。所有这些节点都由 tsubst_copy 来处理。

 

7449   static tree

7450   tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)                    in pt.c

7451   {

7452     enum tree_code code;

7453     tree r;

7454  

7455     if (t == NULL_TREE || t == error_mark_node)

7456       return t;

7457  

7458     code = TREE_CODE (t);

7469  

7460     switch (code)

7461     {

          …

7767       case RECORD_TYPE:

7768       case UNION_TYPE:

7769       case ENUMERAL_TYPE:

7770       case INTEGER_TYPE:

7771       case TEMPLATE_TYPE_PARM:

7772       case TEMPLATE_TEMPLATE_PARM:

7773       case BOUND_TEMPLATE_TEMPLATE_PARM:

7774       case TEMPLATE_PARM_INDEX:

7775       case POINTER_TYPE:

7776       case REFERENCE_TYPE:

7777       case OFFSET_TYPE:

7778       case FUNCTION_TYPE:

7779       case METHOD_TYPE:

7780       case ARRAY_TYPE:

7781       case TYPENAME_TYPE:

7782       case UNBOUND_CLASS_TEMPLATE:

7783       case TYPEOF_TYPE:

7784       case TYPE_DECL:

7785         return tsubst (t, args, complain, in_decl);

          …

7816     }

7817   }

 

对于这些节点,再一次调用了 tsubst 。记得 t 指向模板参数,而 args 持有模板的实参。

 

6681   static tree

6682   tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

6685

6686    if (t == NULL_TREE || t == error_mark_node

6687      || t == integer_type_node

6688      || t == void_type_node

6689      || t == char_type_node

6690        || t == unknown_type_node

6691      || TREE_CODE (t) == NAMESPACE_DECL)

6692        return t;

6693

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

6698  

6699     my_friendly_assert (type != unknown_type_node, 20030716);

6700  

6701     if (type && TREE_CODE (t) != FUNCTION_DECL

6702        && TREE_CODE (t) != TYPENAME_TYPE

6703        && TREE_CODE (t) != TEMPLATE_DECL

6704        && TREE_CODE (t) != IDENTIFIER_NODE

6705        && TREE_CODE (t) != FUNCTION_TYPE

6706        && TREE_CODE (t) != METHOD_TYPE)

6707       type = tsubst (type, args, complain, in_decl);

6708     if (type == error_mark_node)

6709       return error_mark_node;

6710  

6711     if (DECL_P (t))

6712       return tsubst_decl (t, args, type, complain);

6713  

6714     switch (TREE_CODE (t))

6715     {

          …

6776       case TEMPLATE_TYPE_PARM:

6777       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785         r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6790         {

6791           idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795         {

6796           idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802           tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             return error_mark_node;

6810           else if (arg != NULL_TREE)

6811           {

6812             if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)

6813              {

                  …

6818             }

6819             else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6820             {

                  …

6843             }

6844             else

6845               /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.  */

6846               return arg;

6847           }

6848         }

            …

6907       }

          …

7304     }

7305   }

 

节点 TEMPLATE_TEMPLATE_PRAM 有空的 type 域。而在 6791 行,根据相应的 TEMPLATE_PARM_INDEX 节点,把 idx level 分别设置为 0 1 。在 6806 arg 指向“ SingleThreaded ”的 TEMPALTE_DECL 节点。当把这个节点返回给 tsubst_template_arg 时,在 5713 行的 uses_template_parms 对这个节点返回 0 ,因为这个节点不是依赖性的。而这个节点被继续返回。

外层模板的第二个参数是下图中的 TEMPLATE_PARM_INDEX 节点。而在 6806 行, arg 指向上一图中的 INTEGER_CST 整形常量 4096 ;并且它同样在 6846 行被返回。

点此打开

类似的还有外层模板的第三个参数,在前一节我们忽略了它。对于内层模板,其参数是下图中的 TEMPLATE_TYPE_PARM 节点。

t3

在图中被相应的 TEMPLATE_PARM_INDEX 所记录的 level 2 ,同时 args 所显示的 level 1 ;下面是 tsubst 中为这个节点执行的代码。

 

6681   static tree

6682   tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)                                    in pt.c

6683   {

6684     tree type, r;

        …

6694     if (TREE_CODE (t) == IDENTIFIER_NODE)

6695       type = IDENTIFIER_TYPE_VALUE (t);

6696     else

6697       type = TREE_TYPE (t);

6714     switch (TREE_CODE (t))

6715     {

          …

6776       case TEMPLATE_TYPE_PARM:

6777       case TEMPLATE_TEMPLATE_PARM:

6778       case BOUND_TEMPLATE_TEMPLATE_PARM:

6779       case TEMPLATE_PARM_INDEX:

6780       {

6781         int idx;

6782         int level;

6783         int levels;

6784  

6785          r = NULL_TREE;

6786  

6787         if (TREE_CODE (t) == TEMPLATE_TYPE_PARM

6788            || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM

6789            || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6790         {

6791           idx = TEMPLATE_TYPE_IDX (t);

6792           level = TEMPLATE_TYPE_LEVEL (t);

6793         }

6794         else

6795         {

6796           idx = TEMPLATE_PARM_IDX (t);

6797           level = TEMPLATE_PARM_LEVEL (t);

6798         }

6799  

6800         if (TREE_VEC_LENGTH (args) > 0)

6801         {

6802            tree arg = NULL_TREE;

6803  

6804           levels = TMPL_ARGS_DEPTH (args);

6805           if (level <= levels)

6806             arg = TMPL_ARG (args, level, idx);

6807  

6808           if (arg == error_mark_node)

6809             return error_mark_node;

6810            else if (arg != NULL_TREE)

6811           {

                …

6847           }

6848         }

6849         else

6850           abort ();

6851  

6852         if (level == 1)

6853           /* This can happen during the attempted tsubst'ing in

6854             unify. This means that we don't yet have any information

6855             about the template parameter in question.  */

6856           return t;

6857  

6858         /* If we get here, we must have been looking at a parm for a

6859           more deeply nested template. Make a new version of this

6860           template parameter, but with a lower level.  */

6861         switch (TREE_CODE (t))

6862         {

6863           case TEMPLATE_TYPE_PARM:

6864           case TEMPLATE_TEMPLATE_PARM:

6865           case BOUND_TEMPLATE_TEMPLATE_PARM:

6866             if (cp_type_quals (t))

6867             {

                  …

6873             }

6874             else

6875             {

6876               r = copy_type (t);

6877               TEMPLATE_TYPE_PARM_INDEX (r)

6878                 = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),

6879                                           r, levels);

6880               TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);

6881               TYPE_MAIN_VARIANT (r) = r;

6882               TYPE_POINTER_TO (r) = NULL_TREE;

6883               TYPE_REFERENCE_TO (r) = NULL_TREE;

6884  

6885               if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)

6886               {

                    …

6894               }

6895              }

6896             break ;

6897  

6898           case TEMPLATE_PARM_INDEX:

6899             r = reduce_template_parm_level (t, type, levels);

6900             break ;

6901          

6902           default :

6903             abort ();

6904         }

6905  

6906         return r;

6907       }

          …

7304     }

7305   }

 

上面在 6878 行, TEMPLATE_TYPE_PARM_INDEX 提取在 TEMPLATE_TYPE_PARM 节点的 value 域中的节点,它是 TEMPLATE_PARM_INDEX 节点。

 

2128   static tree

2129   reduce_template_parm_level (tree index, tree type, int levels)                              in pt.c

2130   {

2131     if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE

2132        || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))

2133           != TEMPLATE_PARM_LEVEL (index) - levels))

2134     {

2135       tree orig_decl = TEMPLATE_PARM_DECL (index);

2136       tree decl, t;

2137        

2138       decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);

2139       TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);

2140       TREE_READONLY (decl) = TREE_READONLY (orig_decl);

2141       DECL_ARTIFICIAL (decl) = 1;

2142       SET_DECL_TEMPLATE_PARM_P (decl);

2143        

2144       t = build_template_parm_index (TEMPLATE_PARM_IDX (index),

2145                                 TEMPLATE_PARM_LEVEL (index) - levels,

2146                                 TEMPLATE_PARM_ORIG_LEVEL (index),

2147                                 decl, type);

2148       TEMPLATE_PARM_DESCENDANTS (index) = t;

2149  

2150       /* Template template parameters need this.  */

2151       DECL_TEMPLATE_PARMS (decl)

2152         = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));

2153     }

2154  

2155     return TEMPLATE_PARM_DESCENDANTS (index);

2156   }

 

上面,一个新的带有减少的 level TEMPLATE_PARM_INDEX 被构建来代表内层模板参数的具现。并且这个节点作为原始 TEMPLATE_PARM_INDEX 节点的直接后代。

t4

然后在 tsubst 6823 行,下图中的 BOUND_TEMPLATE_TEMPLATE_PARM 节点所包含的参数,嵌套的 tsubst 为之构建了 argvec

点此打开

继续在 tsubst 中处理 BOUND_TEMPLATE_TEMPLATE_PARM 节点,记得下面的 arg 指向下图中“ SingleThreaded TEMPLATE_DECL 。因为现在我们正在具现外层的模板,首先具现内层模板是先决条件。这通过下面的 lookup_template_class 隐蔽地完成。

 

tsubst (continue)

 

6828               /* We can get a TEMPLATE_TEMPLATE_PARM here when

6829                 we are resolving nested-types in the signature of

6830                 a member function templates.

6831                 Otherwise ARG is a TEMPLATE_DECL and is the real

6832                 template to be instantiated.  */

6833               if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)

6834                 arg = TYPE_NAME (arg);

6835  

6836               r = lookup_template_class (arg,

6837                                     argvec, in_decl,

6838                                      DECL_CONTEXT (arg),

6839                                     /*entering_scope=*/ 0,

6840                                     complain);

6841               return cp_build_qualified_type_real

6842                        (r, TYPE_QUALS (t), complain);

6843             }

6844             else

6845               /* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.  */

6846               return arg;

6847           }

6848         }

6849         else

6850           abort ();

 

那么在调用 lookup_template_class 时,实参 dl 是下图中红色的 TEMPLATE_DECL arglist 是上面 tusbst 中的 argvec ,而 context 是作用域“ Loki ”。

点此打开

 

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     {

          …

4162     }

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

4164     {

          …

4177     }

4178     else if (TREE_CODE (d1) == ENUMERAL_TYPE

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

4180     {

          …

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     }

        …

4219     complain &= ~tf_user;

4220    

4221     if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))

4222     {

          …

4259     }

4260     else

4261     {

4262       tree template_type = TREE_TYPE (template);

4263       tree gen_tmpl;

4264       tree type_decl;

4265       tree found = NULL_TREE;

4266       tree *tp;

4267       int arg_depth;

4268       int parm_depth;

4269       int is_partial_instantiation;

4270  

4271       gen_tmpl = most_general_template (template);

4272       parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);

4273       parm_depth = TMPL_PARMS_DEPTH (parmlist);

4274       arg_depth = TMPL_ARGS_DEPTH (arglist);

4275  

4276       if (arg_depth == 1 && parm_depth > 1)

4277      {

            …

4294       }

4295

4296       /* Now we should have enough arguments.  */

4297       my_friendly_assert (parm_depth == arg_depth, 0);

4298      

4299       /* From here on, we're only interested in the most general

4300          template.  */

4301       template = gen_tmpl;

4302  

4303       /* Calculate the BOUND_ARGS. These will be the args that are

4304         actually tsubst'd into the definition to create the

4305         instantiation.  */

4306       if (parm_depth > 1)

4307       {

            …

4344       }

4345       else

4346         arglist

4347             = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),

4348                                   INNERMOST_TEMPLATE_ARGS (arglist),

4349                                   template,

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

4351  

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

 

上面的 parmlist 是被“ SingleThreaded ”的 TEMPLATE_DECL 中的 arguments 域所指向的 tree_list 链。因此下面的实参 parms 是被这个 tree_list value 域所引用的 tree_vec ;这是在声明中的参数。接下来的 INNERMOST_TEMPLATE_ARGS 访问上面 argvec 的第二个元素——内层模板的实参。

 

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

        …

3838     new_inner_args = make_tree_vec (nparms);

3839     new_args = add_outermost_template_args (args, new_inner_args);

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   }

 

因为 parms args 都是大小为 1 tree_vec 3829 行的 add_outermost_template_args 不做任何事。接着在 3850 行, arg 指向新构建的 TEMPLATE_TYPE_PARM 节点。

 

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

        …

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   }

 

TEMPLATE_TYPE_PARM 节点被视为类型 所以 3676 行的 is_type 因为 TYPE_P arg 返回 true 。接着在 3761 行,因为 arg 不是一个 tree_list groktypename 仅是把 arg 返回来。注意到在 lookup_template_class 4347 行, arg 被替换入 arglist

 

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

        

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

4432                      complain, in_decl);

4433       if (!context)

4434         context = global_namespace ;

4435  

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 是“ SingleThreaded ”的 RECORD_TYPE 节点,虽然 4364 行的 comp_template_args 发现其实参与 arglist 相同,但我们不是在类作用域中( current_class_type NULL ),我们不得不放弃这个找到的 RECORD_TYPE 节点。

接下来 context 是名字空间“ Loki ”, 4431 行的 tsubst 不做任何事,只是返回这个节点。后面的代码为基类具现创建了 RECORD_TYPE 及相关的节点。这些节点显示如下。最后该 RECORD_TYPE 节点被返回到 instantiate_class_template 5439 行。

点此打开

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值