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

5.12.4.1.2.1.  处理非类型参数

在解析了这个非类型模板参数之后,下一步,需要处理这个参数来完成相关的子树并插入中间树。

 

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     {

2190       my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);

2191       /* is a const-param */

2192       parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),

2193                           PARM, 0, NULL);

2194       SET_DECL_TEMPLATE_PARM_P (parm);

2195  

2196       /* [temp.param]

2197  

2198         The top-level cv-qualifiers on the template-parameter are

2199         ignored when determining its type.  */

2200       TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));

2201  

2202       /* A template parameter is not modifiable.  */

2203       TREE_READONLY (parm) = TREE_CONSTANT (parm) = 1;

2204       if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))

2205         TREE_TYPE (parm) = void_type_node;

2206       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));

2207       TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;

2208       DECL_INITIAL (parm) = DECL_INITIAL (decl)

2209                = build_template_parm_index (idx, processing_template_decl,

2210                                         processing_template_decl,

2211                                         decl, TREE_TYPE (parm));

2212     }

2213     else

2214     {

         …

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   }

 

对于我们的例子:“ size_t chunkSize = 4096 ”,相关的子树被 process_template_parm 的参数 next 指向,在上面的 2172 行, parm 指向“ size_t chunSize ”部分。因此在调用 grokdeclarator 时,参数 declarator 指向节点“ chunkSize ”,而参数 declspecs 指向节点“ size_t ”。

 

6462   tree

6463   grokdeclarator (tree declarator,                                                                 in decl.c

6464                tree declspecs,

6465                enum decl_context decl_context,

6466                int initialized,

6467                tree* attrlist)

6468   {

6469     RID_BIT_TYPE specbits;

6470     int nclasses = 0;

6471     tree spec;

6472     tree type = NULL_TREE;

6473     int longlong = 0;

6474     int type_quals;

6475     int virtualp, explicitp, friendp, inlinep, staticp;

6476     int explicit_int = 0;

6477     int explicit_char = 0;

6478     int defaulted_int = 0;

6479     int extern_langp = 0;

6480     tree dependant_name = NULL_TREE;

6481    

6482     tree typedef_decl = NULL_TREE;

6483     const char *name;

6484     tree typedef_type = NULL_TREE;

6485     int funcdef_flag = 0;

6486     enum tree_code innermost_code = ERROR_MARK;

6487     int bitfield = 0;

6488   #if 0

6489     /* See the code below that used this.  */

6490     tree decl_attr = NULL_TREE;

6491   #endif

6492  

6493     /* Keep track of what sort of function is being processed

6494       so that we can warn about default return values, or explicit

6495       return values which do not match prescribed defaults.  */

6496     special_function_kind sfk = sfk_none;

6497  

6498     tree dname = NULL_TREE;

6499     tree ctype = current_class_type ;

6500     tree ctor_return_type = NULL_TREE;

6501     enum overload_flags flags = NO_SPECIAL;

6502     tree quals = NULL_TREE;

6503     tree raises = NULL_TREE;

6504     int template_count = 0;

6505     tree in_namespace = NULL_TREE;

6506     tree returned_attrs = NULL_TREE;

6507     tree scope = NULL_TREE;

6508     tree parms = NULL_TREE;

6509  

6510     RIDBIT_RESET_ALL (specbits);

6511     if (decl_context == FUNCDEF)

6512       funcdef_flag = 1, decl_context = NORMAL;

6513     else if (decl_context == MEMFUNCDEF)

6514       funcdef_flag = -1, decl_context = FIELD;

6515     else if (decl_context == BITFIELD)

6516       bitfield = 1, decl_context = FIELD;

6517  

6518     /* Look inside a declarator for the name being declared

6519       and get it as a string, for an error message.  */

6520     {

6521       tree *next = &declarator;

6522       tree decl;

6523       name = NULL;

6524  

6525       while (next && *next)

6526       {

6527         decl = *next;

6528         switch (TREE_CODE (decl))

6529         {

              …

6629           case IDENTIFIER_NODE:

6630             if (TREE_CODE (decl) == IDENTIFIER_NODE)

6631               dname = decl;

6632  

6633             next = 0;

6634  

6635             if (C_IS_RESERVED_WORD (dname))

6636             {

6637               error ("declarator-id missing; using reserved word `%D'",

6638                     dname);

6639               name = IDENTIFIER_POINTER (dname);

6640             }

6641             else if (!IDENTIFIER_TYPENAME_P (dname))

6642               name = IDENTIFIER_POINTER (dname);

6643             else

6644             {

6645               my_friendly_assert (flags == NO_SPECIAL, 154);

6646               flags = TYPENAME_FLAG;

6647               ctor_return_type = TREE_TYPE (dname);

6648               sfk = sfk_conversion;

6649               if (is_typename_at_global_scope (dname))

6650                 name = IDENTIFIER_POINTER (dname);

6651                else

6652                 name = "<invalid operator>";

6653             }

6654             break ;

             …

6784         }

6785       }

6786     }

6787  

6788     /* A function definition's declarator must have the form of

6789       a function declarator.  */

6790  

6791     if (funcdef_flag && innermost_code != CALL_EXPR)

6792       return 0;

        …

6828     /* Look through the decl specs and record which ones appear.

6829       Some typespecs are defined as built-in typenames.

6830       Others, the ones that are modifiers of other types,

6831       are represented by bits in SPECBITS: set the bits for

6832       the modifiers that appear. Storage class keywords are also in SPECBITS.

6833  

6834       If there is a typedef name or a type, store the type in TYPE.

6835       This includes builtin typedefs such as `int'.

6836  

6837       Set EXPLICIT_INT if the type is `int' or `char' and did not

6838       come from a user typedef.

6839  

6840       Set LONGLONG if `long' is mentioned twice.

6841  

6842       For C++, constructors and destructors have their own fast treatment.  */

6843  

6844     for (spec = declspecs; spec; spec = TREE_CHAIN (spec))

6845     {

6846       int i;

6847       tree id;

6848  

6849       /* Certain parse errors slip through. For example,

6850         `int class;' is not caught by the parser. Try

6851          weakly to recover here.  */

6852       if (TREE_CODE (spec) != TREE_LIST)

6853         return 0;

6854  

6855       id = TREE_VALUE (spec);

6856  

6857       /* If the entire declaration is itself tagged as deprecated then

6858         suppress reports of deprecated items.  */

6859       if (!adding_implicit_members && id && TREE_DEPRECATED (id))

6860       {

6861         if (deprecated_state != DEPRECATED_SUPPRESS)

6862           warn_deprecated_use (id);

6863       }

6864  

6865       if (TREE_CODE (id) == IDENTIFIER_NODE)

6866       {

6867         if (id == ridpointers [(int) RID_INT]

6868            || id == ridpointers [(int) RID_CHAR]

6869            || id == ridpointers [(int) RID_BOOL]

6870            || id == ridpointers [(int) RID_WCHAR])

6871         {

               …

6888         }

6889          /* C++ aggregate types.  */

6890         if (IDENTIFIER_HAS_TYPE_VALUE (id))

6890         {

              …

6896         }

            …

6947         if (type)

6948           error ("two or more data types in declaration of `%s'", name);

6949         else if (TREE_CODE (id) == IDENTIFIER_NODE)

6950         {

6951           tree t = lookup_name (id, 1);

6952           if (!t || TREE_CODE (t) != TYPE_DECL)

6953             error ("`%s' fails to be a typedef or built in type",

6954                  IDENTIFIER_POINTER (id));

6955           else

6956           {

6957             type = TREE_TYPE (t);

6958             typedef_decl = t;

6959           }

6960         }

           …

6965       found: ;

6966       }

6967  

6968   #if 0

6969     /* See the code below that used this.  */

6970     if (typedef_decl)

6971       decl_attr = DECL_ATTRIBUTES (typedef_decl);

6972   #endif

6973     typedef_type = type;

 

对于为 IDENTIFIER_NODE 的声明符,仅字面名被提取,并且这个名字被用于错误信息中以给出清晰的描述。那么对于 declspecs ,它是仅有一个 IDENTIFIER_NODE tree_list ,它为上面的 id 所引用。然后在 6951 行, lookup_name 查找这个非限定名,并返回对应的 TYPE_DECL 节点。注意对于这个案例,解析器能够识别出它是应该 typedef 。因此在 6957 行的变量 type 指向 long_unsigned_type_node (假定 size_t typedef unsigned long ),而 typedef_decl 指向对应的 TYPE_DECL

 

grokdeclarator (continue)

 

8163     {

8164       tree decl;

8165  

8166       if (decl_context == PARM)

8167       {

8168         decl = cp_build_parm_decl (declarator, type);

8169  

8170          bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,

8171                      inlinep, friendp, raises != NULL_TREE);

8172       }

          …

8750       return decl;

8751     }

8752   }

 

与类型参数相同,需要构建 TEMPLATE_PARM_INDEX 节点来代表这个参数。注意到模板参数 chunkSize 只能是常量。一个 CONST_DECL 节点被解析器自动创建来反映这一事实。从这里所构建的节点,可以很容易地辨别,这是一个模板声明中的参数声明的常量声明。

点此打开

107 :构建的非类型模板参数

然后这个名字必须被加入当前作用域,使得名字查找过程可以更有效地找到正确的声明。函数 pushdecl 执行与前面模板模板参数相同的代码,在这一点之后的参数列表看起来如下。

点此打开

108 :加入非类型参数

看到“ size_t ”的 IDENTIFIER_NODE bindings 域现在指向 CONST_DECL 节点,它表示这个布局绑定的值。名字查找过程将返回这个绑定,作为在该作用域中查找的结果。

然后接下来的参数以同样的方式、过程来解析。为了尽量保持简洁,我们跳过这个过程,而中间树的布局可以相应地,很容易地画出来。当完成模板参数的解析时, end_template_parm_list 依照下图给参数打包(注意参数“ size_t maxSmallObjectSize ”部分没有画出)。

点此打开

109 end_template_parm_list 的结果

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值