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

5.12.5.2.2.2.1.3.    为具现构建 RECORD_TYPE

最后,在 cp_parser_init_declarator 10181 行, cp_finish_decl 完成这个声明。因为它是在一个函数中的声明,在下面 4957 行,一个新的 DECL_STMT 被插入到对应的 stmt-tree ,之后我们得到如下的中间树。

点此打开

 

4786   void

4787   cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)                           in decl.c

4788   {

4789     tree type;

4790     tree ttype = NULL_TREE;

4791     tree cleanup;

4792     const char *asmspec = NULL;

4793     int was_readonly = 0;

4794     bool var_definition_p = false;

4795  

4796     if (decl == error_mark_node)

4797       return ;

4798     else if (! decl)

4799     {

4800       if (init)

4801         error ("assignment (not initialization) in declaration");

4802       return ;

4803     }

4804  

4805     my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);

        …

4821     type = TREE_TYPE (decl);

        …

4844     /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */

4845     my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);

        …

4953     /* Add this declaration to the statement-tree. This needs to happen

4954       after the call to check_initializer so that the DECL_STMT for a

4955       reference temp is added before the DECL_STMT for the reference itself.  */

4956     if (at_function_scope_p ())

4957       add_decl_stmt (decl);

4958  

4959     if (TREE_CODE (decl) == VAR_DECL)

4960       layout_var_decl (decl);

 

接下来需要由下面的 layout_var_decl 来完成该类型的定义。

 

4043   static void

4044   layout_var_decl (tree decl)                                                                                     in decl.c

4045   {

4046     tree type = TREE_TYPE (decl);

4047   #if 0

4048     tree ttype = target_type (type);

4049   #endif

4050  

4051     /* If we haven't already layed out this declaration, do so now.

4052        Note that we must not call complete type for an external object

4053        because it's type might involve templates that we are not

4054        supposed to instantiate yet.  (And it's perfectly valid to say

4055        `extern X x' for some incomplete type `X'.)  */

4056     if (!DECL_EXTERNAL (decl))

4057       complete_type (type);

4058     if (!DECL_SIZE (decl)

4059         && TREE_TYPE (decl) != error_mark_node

4060         && (COMPLETE_TYPE_P (type)

4061             || (TREE_CODE (type) == ARRAY_TYPE

4062               && !TYPE_DOMAIN (type)

4063               && COMPLETE_TYPE_P (TREE_TYPE (type)))))

4064       layout_decl (decl, 0);

4065  

4066     if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)

4067     {

4068       /* An automatic variable with an incomplete type: that is an error.

4069         Don't talk about array types here, since we took care of that

4070         message in grokdeclarator.  */

4071       error ("storage size of `%D' isn't known", decl);

4072       TREE_TYPE (decl) = error_mark_node;

4073     }

4074   #if 0

       …

4084   #endif

4085  

4086     if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))

4087         && DECL_SIZE (decl) != NULL_TREE

4088         && ! TREE_CONSTANT (DECL_SIZE (decl)))

4089     {

4090       if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)

4091         constant_expression_warning (DECL_SIZE (decl));

4092       else

4093         error ("storage size of `%D' isn't constant", decl);

4094     }

4095  

4096     if (TREE_STATIC (decl)

4097         && !DECL_ARTIFICIAL (decl)

4098         && current_function_decl

4099         && DECL_CONTEXT (decl) == current_function_decl )

4100       push_local_name (decl);

4101   }

 

在这里, type 是刚创建的 RECORD_TYPE ,而 decl 是一个非外部声明( non-external declaration )。因此 type 应该已经在这个编译单元中定义,现在可以完成其定义了。

 

116     tree

117     complete_type (tree type)                                                                         in typeck.c

118     {

119       if (type == NULL_TREE)

120        /* Rather than crash, we return something sure to cause an error

121          at some point.  */

122        return error_mark_node;

123   

124      if (type == error_mark_node || COMPLETE_TYPE_P (type))

125        ;

126      else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))

127      {

128        tree t = complete_type (TREE_TYPE (type));

129        if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))

130          layout_type (type);

131        TYPE_NEEDS_CONSTRUCTING (type)

132           = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));

133        TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)

134           = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));

135      }

136      else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))

137        instantiate_class_template (TYPE_MAIN_VARIANT (type));

138   

139      return type;

140    }

 

对于模板定义,在具现点生成一个新类型。该新类型的定义也在该点完毕(因为其 TREE_SIZE 域是 NULL ,这是一个不完整的类型)。

 

5274   tree

5275   instantiate_class_template (tree type)                                                                in pt.c

5276   {

5277     tree template, args, pattern, t, member;

5278     tree typedecl;

5279     tree pbinfo;

5280    

5281     if (type == error_mark_node)

5282       return error_mark_node;

5283  

5284     if (TYPE_BEING_DEFINED (type)

5285         || COMPLETE_TYPE_P (type)

5286         || dependent_type_p (type))

5287       return type;

5288  

5289     /* Figure out which template is being instantiated.  */

5290     template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));

5291     my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);

5292  

5293     /* Figure out which arguments are being used to do the

5294       instantiation.  */

5295     args = CLASSTYPE_TI_ARGS (type);

5296  

5297     /* Determine what specialization of the original template to

5298       instantiate.  */

5299     t = most_specialized_class (template, args);

5300     if (t == error_mark_node)

5301     {

          …

5315     }

5316  

5317     if (t)

5318       pattern = TREE_TYPE (t);

5319     else

5320       pattern = TREE_TYPE (template);

5321  

5322     /* If the template we're instantiating is incomplete, then clearly

5323       there's nothing we can do.  */

5324     if (!COMPLETE_TYPE_P (pattern))

5325       return type;

5326  

5327     /* If we've recursively instantiated too many templates, stop.  */

5328     if (! push_tinst_level (type))

5329       return type;

5330  

5331     /* Now we're really doing the instantiation. Mark the type as in

5332       the process of being defined.  */

5333     TYPE_BEING_DEFINED (type) = 1;

 

注意到在上面的 5320 行, pattern 指向最泛化模板所对应的 RECORD_TYPE (也即模板定义中出现的“ SmallObject ”),其 TYPE_SIZE 域在 finish_struct 中被初始化为 bitsize_zero_node size_zero_node 5299 行的 most_specialized_class 返回匹配的特化程度最高的定义,找不到或没有特化的定义则返回 NULL

虽然在理论上具现的层数是没有限制的,但是在实现中必须防止由于编程或者实现的失误而导致的无限模板具现。这样具现的层数必须是有限制的。在 GCC ,版本 3.4.6 中,全局变量 max_tinst_depth 保存这个限制。其值现在是 500

 

4850   int

4851   push_tinst_level (tree d)                                                                                  in pt.c

4852   {

4853     tree new;

4854  

4855     if (tinst_depth >= max_tinst_depth )

4856     {

4857       /* If the instantiation in question still has unbound template parms,

4858         we don't really care if we can't instantiate it, so just return.

4859         This happens with base instantiation for implicit `typename'.  */

4860       if (uses_template_parms (d))

4861         return 0;

4862  

4863       last_template_error_tick = tinst_level_tick ;

4864       error ("template instantiation depth exceeds maximum of %d (use -ftemplate-depth-NN to increase the maximum) instantiating `%D'",

4865              max_tinst_depth , d);

4866  

4867       print_instantiation_context ();

4868  

4869       return 0;

4870     }

4871  

4872     new = build_expr_wfl (d, input_filename, input_line, 0);

4873     TREE_CHAIN (new) = current_tinst_level ;

4874     current_tinst_level = new;

4875  

4876     ++tinst_depth ;

4877   #ifdef GATHER_STATISTICS

4878     if (tinst_depth > depth_reached )

4879       depth_reached = tinst_depth ;

4880   #endif

4881  

4882     ++tinst_level_tick ;

4883     return 1;

4884   }

 

上面在 4872 行,节点 EXPR_WITH_FILE_LOCATION 被构建来记录具现所在的文件及行数。并且这个节点被串接入全局链表 current_tinst_level 用于诊断的目的。

 

instantiate_class_template (continue)

 

5335     /* We may be in the middle of deferred access check. Disable

5336       it now.  */

5337     push_deferring_access_checks (dk_no_deferred);

5338  

5339     push_to_top_level ();

5340  

5341     if (t)

5342     {

          …

5367     }

5368  

5369     SET_CLASSTYPE_INTERFACE_UNKNOWN (type);

5370  

5371     /* Set the input location to the template definition. This is needed

5372       if tsubsting causes an error.  */

5373     input_location = DECL_SOURCE_LOCATION (TYPE_NAME (pattern));

5374  

5375     TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);

5376     TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);

5377     TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);

5378     TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);

5379     TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);

5380     TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);

5381     TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);

5382     TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);

5383     TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);

5384     TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);

5385     TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);

5386     TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);

5387     TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)

5388       = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (pattern);

5389     TYPE_USES_MULTIPLE_INHERITANCE (type)

5390       = TYPE_USES_MULTIPLE_INHERITANCE (pattern);

5391     TYPE_USES_VIRTUAL_BASECLASSES (type)

5392       = TYPE_USES_VIRTUAL_BASECLASSES (pattern);

5393     TYPE_PACKED (type) = TYPE_PACKED (pattern);

5394     TYPE_ALIGN (type) = TYPE_ALIGN (pattern);

5395     TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);

5396     TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */

5397     if (ANON_AGGR_TYPE_P (pattern))

5398       SET_ANON_AGGR_TYPE_P (type);

 

注意上面的 pattern 对应着模板定义中的 RECORD_TYPE ,而 type 对应具现时刻产生的 RECORD_TYPE 。在具现的过程中,我们需要进入具现类型及其子类(如果有子类的话)的作用域,这将改变当前的作用域。因此在第一步,我们需要跑到绑定域的顶层——全局名字空间( 5339 行的 push_to_top_level ),并缓存当前的作用域层次,由下面的 push_scope pushclass 为我们构建合适的上下文(注意这里的 type pattern context 都是“ Loki ”的 NAMESPACE_DECL ——具现的类型被视为在同一作用域下不同的变种)。

 

instantiate_class_template (continue)

 

5400     pbinfo = TYPE_BINFO (pattern);

5401  

5402   #ifdef ENABLE_CHECKING

5403     if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern))

5404         && ! COMPLETE_TYPE_P (TYPE_CONTEXT (type))

5405          && ! TYPE_BEING_DEFINED (TYPE_CONTEXT (type)))

5406       /* We should never instantiate a nested class before its enclosing

5407         class; we need to look up the nested class by name before we can

5408         instantiate it, and that lookup should instantiate the enclosing

5409         class.  */

5410       abort ();

5411   #endif

5412  

5413     if (BINFO_BASETYPES (pbinfo))

5414     {

5415       tree base_list = NULL_TREE;

5416       tree pbases = BINFO_BASETYPES (pbinfo);

5417       tree paccesses = BINFO_BASEACCESSES (pbinfo);

5418       tree context = TYPE_CONTEXT (type);

5419       bool pop_p;

5420       int i;

5421  

5422       /* We must enter the scope containing the type, as that is where

5423         the accessibility of types named in dependent bases are

5424         looked up from.  */

5425       pop_p = push_scope (context ? context : global_namespace );

5426    

5427       /* Substitute into each of the bases to determine the actual

5428         basetypes.  */

5429       for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)

5430       {

5431         tree base;

5432         tree access;

5433         tree pbase;

5434  

5435         pbase = TREE_VEC_ELT (pbases, i);

5436         access = TREE_VEC_ELT (paccesses, i);

5437  

5438         /* Substitute to figure out the base class.  */

5439         base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);

5440         if (base == error_mark_node)

5441           continue ;

5442     

5443         base_list = tree_cons (access, base, base_list);

5444         TREE_VIA_VIRTUAL (base_list) = TREE_VIA_VIRTUAL (pbase);

5445       }

5446  

5447       /* The list is now in reverse order; correct that.  */

5448       base_list = nreverse (base_list);

5449  

5450       /* Now call xref_basetypes to set up all the base-class

5451         information.  */

5452       xref_basetypes (type, base_list);

5453  

5454       if (pop_p)

5455         pop_scope (context ? context : global_namespace );

5456     }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值