Studying note of GCC-3.4.6 source (133)

5.12.5.2.2.2.1.3.    Generate RECORD_TYPE for the instantiation

At last, at line 10181 in cp_parser_init_declarator , cp_finish_decl closes the declaration. As it is the declaration within a function, a new DECL_STMT is inserted into the stmt-tree at line 4957 below, and after that we gets following intermediate tree.

(Click here for open )

 

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

 

Next it needs complete the definition of the type and the declaration as layout_var_decl in below.

 

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   }

 

At here, type is the RECORD_TYPE just created above, and decl is a non-external declaration. So type is already defined within this translation-unit, and can be completed now.

 

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    }

 

For template definition, a new type is generated at point of instantiation. And the new type’s definition is completed at that point too (it is a incomplete type because its TREE_SIZE field is 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;

 

Note that at line 5320 above, pattern refers to the RECORD_TYPE of the most general template (i.e., “SmallObject” in the template definition), its TYPE_SIZE field is initialized as bitsize_zero_node and size_zero_node in finish_struct for class template definition. At line 5299, most_specialized_class returns the matching most specialized defintion, and in case of no matching or no defining specialization returns NULL.

Though in therory the level of instantiation depth is unlimited, but in implementation it must prevent infinite template instantiation due to mistaken in program or implementation. This instantiation level must be restricted. In GCC, version 3.4.6, global variable max_tinst_depth holds this limitation. Its value now is 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   }

 

Above at line 4872, tree node of EXPR_WITH_FILE_LOCATION is generated to record the file and the line number at point of instantiation. And this node is chained into the global list current_tinst_level for diagnosis purpose.

 

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

 

Note that above pattern refers to the RECORD_TYPE generated from the template defintion, while type points to the RECORD_TYPE created at instantiation. Then during instantiation, we need enter the scope the class and its bases (if there is any), which will change the current scope. So at first step, we need return back to the top level of binding scope – global namespace (push_to_top_level at line 5339) and cache the current scope. In below, push_scope and pushclass will build appropriate context for us (see that context of type and pattern are both NAMESPACE_DECL of “Loki” – every instantiation is regarded as a variant within the same context).

 

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     }

 

for Policy and Practice, 2018, 17(2): 179-195. In this article, Victor Wang Chen Neo examines the implementation of school-based curriculum development (SBCD) in Singapore. SBCD is a process where schools are given greater autonomy to develop and implement their own curriculum, rather than following a standardized national curriculum. The author begins by providing an overview of the history of curriculum development in Singapore, and how the shift towards SBCD came about. He then presents the findings of a study that he conducted, which involved interviews with school leaders who had implemented SBCD in their schools. The author identifies several factors that influenced the successful implementation of SBCD in these schools. These include strong leadership, a clear vision and direction for the school, and a focus on student learning and development. The author also highlights the importance of teacher training and support, as well as collaboration and communication among all stakeholders involved in the curriculum development process. However, the author also notes some challenges that schools face when implementing SBCD. These include a lack of resources, such as time and funding, as well as the need to balance autonomy with accountability to ensure that the curriculum developed meets national standards. Overall, the author suggests that SBCD has the potential to improve the quality of education in Singapore by allowing schools to tailor their curriculum to the needs and interests of their students. However, he also calls for continued support and guidance from the government to ensure that schools are able to implement SBCD effectively.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值