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

5.12.4.1.1.2.  处理模板模板参数

同样地,在解析完模板模板参数后,模板模板参数的子树也需要额外的节点。这是函数 process_template_parm 的任务。注意该函数的参数 next 指向上图中的 parameter

 

2161   tree

2162   process_template_parm (tree list, tree next)                                                       in pt.c

2163   {

2164     tree parm;

2165     tree decl = 0;

2166     tree defval;

2167     int is_type, idx;

2168  

2169     parm = next;

2170     my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);

2171     defval = TREE_PURPOSE (parm);

2172     parm = TREE_VALUE (parm);

2173     is_type = TREE_PURPOSE (parm) == class_type_node;

2174  

2175     if (list)

2176     {

2177       tree p = TREE_VALUE (tree_last (list));

2178  

2179       if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)

2180         idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));

2181       else

2182         idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));

2183       ++idx;

2184     }

2185     else

2186       idx = 0;

2187  

2188     if (!is_type)

2189     {

          …

2212     }

2213     else

2214     {

2215       tree t;

2216       parm = TREE_VALUE (parm);

2217        

2218       if (parm && TREE_CODE (parm) == TEMPLATE_DECL)

2219       {

2220         t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);

2221         /* This is for distinguishing between real templates and template

2222           template parameters */

2223         TREE_TYPE (parm) = t;

2224         TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;

2225         decl = parm;

2226       }

2227       else

2228       {

            …

2232       }

2233          

2234       TYPE_NAME (t) = decl;

2235       TYPE_STUB_DECL (t) = decl;

2236       parm = decl;

2237       TEMPLATE_TYPE_PARM_INDEX (t)

2238            = build_template_parm_index (idx, processing_template_decl,

2239                                     processing_template_decl,

2240                                      decl, TREE_TYPE (parm));

2241     }

2242     DECL_ARTIFICIAL (decl) = 1;

2243     SET_DECL_TEMPLATE_PARM_P (decl);

2244     pushdecl (decl);

2245     parm = build_tree_list (defval, parm);

2246     return chainon (list, parm);

2247   }

 

注意到 idx 0 ;而 processing_template_decl 现在是 1 ,它表示这是最顶层的第一个参数。树节点 TEMPLATE_TYPE_PARM_INDEX 记录了这个信息。然后通过 pushdecl 将把这个子树插入到中间树中。

 

566    tree

567    pushdecl (tree x)                                                                                     in name-lookup.c

568    {

569      tree t;

570      tree name;

571      int need_new_binding;

572   

573      timevar_push (TV_NAME_LOOKUP);

574   

575      need_new_binding = 1;

576   

577      if (DECL_TEMPLATE_PARM_P (x))

578        /* Template parameters have no context; they are not X::T even

579          when declared within a class or namespace.  */

580        ;

581      else

582      {

           …

602      }

603   

604      name = DECL_NAME (x);

605      if (name)

606      {

607        int different_binding_level = 0;

          …

615        /* In case this decl was explicitly namespace-qualified, look it

616          up in its namespace context.  */

617        if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())

618          t = namespace_binding (name, DECL_CONTEXT (x));

619        else

620          t = lookup_name_current_level (name);

          …

743        check_template_shadow (x);

          …

828         /* This name is new in its binding level.

829          Install the new declaration and return it.  */

830        if (namespace_bindings_p ())

831        {

            …

872        }

873        else

874        {

875          /* Here to install a non-global value.  */

876          tree oldlocal = IDENTIFIER_VALUE (name);

877          tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);

878   

879          if (need_new_binding)

880          {

881            push_local_binding (name, x, 0);

882            /* Because push_local_binding will hook X on to the

883              current_binding_level's name list, we don't want to

884              do that again below.  */

885            need_new_binding = 0;

886          }

            …

1003       }

1004  

1005       if (TREE_CODE (x) == VAR_DECL)

1006         maybe_register_incomplete_var (x);

1007     }

1008  

1009     if (need_new_binding)

1010       add_decl_to_level (x,

1011                       DECL_NAMESPACE_SCOPE_P (x)

1012                       ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))

1013                       : current_binding_level);

1014  

1015     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);

1016   }

 

在执行 pushdecl 后,中间树的相关部分将具有如下的结构。

 

点此打开

103 :加入模板模板参数

pushdecl 返回, process_template_parm 余下的部分重新安排 parm ,并剔除无用的节点。如下图所示。

点此打开

104 :完成模板模板参数处理

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值