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

来源:互联网 发布:淘宝怎么看自己退款率 编辑:程序博客网 时间:2024/06/01 09:52

5.12.5.2.2.2.1.3.    为具现构建RECORD_TYPE

最后,在cp_parser_init_declarator10181行,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 (notinitialization) in declaration");

4802       return;

4803     }

4804  

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

       

4821     type = TREE_TYPE (decl);

       

4844     /* Parameters arehandled by store_parm_decls, not cp_finish_decl.  */

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

       

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

4954       after the call tocheck_initializer so that the DECL_STMT for a

4955       reference temp is added beforethe 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'talready layed out this declaration, do so now.

4052        Note that we must not callcomplete type for an external object

4053        because it's type mightinvolve templates that we are not

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

4055        `extern X x' for someincomplete 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 automaticvariable with an incomplete type: that is an error.

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

4070         message ingrokdeclarator.  */

4071       error ("storage size of `%D' isn'tknown", 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'tconstant", 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 thancrash, we return something sure to cause an error

121          at somepoint.  */

122        returnerror_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       returnerror_mark_node;

5283  

5284     if (TYPE_BEING_DEFINED (type)

5285         || COMPLETE_TYPE_P (type)

5286         || dependent_type_p (type))

5287       returntype;

5288  

5289    /* Figure out whichtemplate 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 whicharguments are being used to do the

5294       instantiation.  */

5295    args = CLASSTYPE_TI_ARGS (type);

5296  

5297     /* Determine whatspecialization 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 templatewe're instantiating is incomplete, then clearly

5323       there's nothing we cando.  */

5324     if (!COMPLETE_TYPE_P (pattern))

5325       returntype;

5326  

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

5328     if (! push_tinst_level(type))

5329       returntype;

5330  

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

5332       the process of beingdefined.  */

5333     TYPE_BEING_DEFINED (type) = 1;

 

注意到在上面的5320行,pattern指向最泛化模板所对应的RECORD_TYPE(也即模板定义中出现的“SmallObject”),其TYPE_SIZE域在finish_struct中被初始化为bitsize_zero_nodesize_zero_node5299行的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 theinstantiation in question still has unbound template parms,

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

4859         This happens with baseinstantiation 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 depthexceeds 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 themiddle 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 inputlocation to the template definition. This is needed

5372       if tsubsting causes anerror.  */

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_scopepushclass为我们构建合适的上下文(注意这里的typepatterncontext都是“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 shouldnever instantiate a nested class before its enclosing

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

5408         instantiate it, and thatlookup 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 enterthe scope containing the type, as that is where

5423         the accessibility of typesnamed in dependent bases are

5424         looked up from.  */

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

5426    

5427       /* Substituteinto 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         /* Substituteto 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 isnow in reverse order; correct that.  */

5448       base_list = nreverse (base_list);

5449  

5450       /* Now callxref_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     }

 

原创粉丝点击