Studying note of GCC-3.4.6 source (124)

5.12.4.2.2.2.3.          Finish template-id

If template-name is an IDENTIFER_NODE, it maybe a member template; and if it is a TEMPLATE_DECL of class template, the template-id itself is a class-name; and if it is FUNCTION_DECL, OVERLOAD or METHOD_DECL, the template-id is a function-name.

So if template-name is a class template, the template-id may name a new class, for which case we should create corresponding class type by finish_template_type . It is a very complex procedure, later section will give an example to go through the function.

 

cp_parser_template_id (continue)

 

7991   /* Build a representation of the specialization.  */

7992   if (TREE_CODE (template) == IDENTIFIER_NODE)

7993     template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);

7994   else if (DECL_CLASS_TEMPLATE_P (template)

7995         || DECL_TEMPLATE_TEMPLATE_PARM_P (template))

7996     template_id

7997       = finish_template_type (template, arguments,

7998                           cp_lexer_next_token_is (parser->lexer,

7999                                               CPP_SCOPE));

8000   else

8001   {

8002     /* If it's not a class-template or a template-template, it should be

8003       a function-template.  */

8004     my_friendly_assert ((DECL_FUNCTION_TEMPLATE_P (template)

8005                      || TREE_CODE (template) == OVERLOAD

8006                      || BASELINK_P (template)),

8007                       20010716);

8008      

8009     template_id = lookup_template_function (template, arguments);

8010   }

8011  

8012   /* Retrieve any deferred checks. Do not pop this access checks yet

8013     so the memory will not be reclaimed during token replacing below.  */

8014   access_check = get_deferred_access_checks ();

 

If template-name is an IDNETIFIER_NODE, the resulting TEMPLATE_ID_EXPR is built by build_min_nt . The function builds a tree node of tree_exp.

 

4069 tree

4070 build_min_nt (enum tree_code code, ...)                                                            in tree.c

4071 {

4072    tree t;

4073    int length;

4074    int i;

4075    va_list p;

4076

4077    va_start (p, code);

4078

4079    t = make_node (code);

4080    length = TREE_CODE_LENGTH (code);

4081    TREE_COMPLEXITY (t) = input_line;

4082

4083    for (i = 0; i < length; i++)

4084    {

4085      tree x = va_arg (p, tree);

4086      TREE_OPERAND (t, i) = x;

4087    }

4088

4089    va_end (p);

4090    return t;

4091 }

 

If the template-name names a function template, the TEMPLATE_ID_EXPR node is created by lookup_template_function . A BASELINK node is a reference to a member function or member functions from a base class. Note that in this case in the TEMPLATE_ID_EXPR generated, its type is unknonw_type_node , which will force the front-end to invoke instantiate_type later to resolve its type.

 

4069 tree

4070 lookup_template_function (tree fns, tree arglist)                                                  in pt.c

4071 {

4072    tree type;

4073

4074    if (fns == error_mark_node || arglist == error_mark_node)

4075      return error_mark_node;

4076

4077    my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726);

4078    my_friendly_assert (fns && (is_overloaded_fn (fns)

4079                            || TREE_CODE (fns) == IDENTIFIER_NODE),

4080                    20050608);

4081

4082    if (BASELINK_P (fns))

4083    {

4084      BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,

4085                                         unknown_type_node,

4086                                        BASELINK_FUNCTIONS (fns),

4087                                        arglist);

4088      return fns;

4089    }

4090

4091    type = TREE_TYPE (fns);

4092    if (TREE_CODE (fns) == OVERLOAD || !type)

4093      type = unknown_type_node;

4094   

4095    return build (TEMPLATE_ID_EXPR, type, fns, arglist);

4096 }

 

Then corresponding tokens are grouped as CPP_TEMPLATE_ID; similarly there is another group - NESTED_NAME_SPECFIER.

 

cp_parser_template_id (continue)

 

8016    /* If parsing tentatively, replace the sequence of tokens that makes

8017      up the template-id with a CPP_TEMPLATE_ID token. That way,

8018      should we re-parse the token stream, we will not have to repeat

8019      the effort required to do the parse, nor will we issue duplicate

8020      error messages about problems during instantiation of the

8021      template.  */

8022    if (start_of_id >= 0)

8023    {

8024      cp_token *token;

8025

8026      /* Find the token that corresponds to the start of the

8027        template-id.  */

8028      token = cp_lexer_advance_token (parser->lexer,

8029                                  parser->lexer->first_token,

8030                                  start_of_id);

8031

8032      /* Reset the contents of the START_OF_ID token.  */

8033      token->type = CPP_TEMPLATE_ID;

8034      token->value = build_tree_list (access_check, template_id);

8035      token->keyword = RID_MAX;

8036      /* Purge all subsequent tokens.  */

8037      cp_lexer_purge_tokens_after (parser->lexer, token);

8038

8039      /* ??? Can we actually assume that, if template_id ==

8040        error_mark_node, we will have issued a diagnostic to the

8041        user, as opposed to simply marking the tentative parse as

8042        failed?  */

8043      if (cp_parser_error_occurred (parser) && template_id != error_mark_node)

8044        error ("parse error in template argument list");

8045    }

8046

8047    pop_deferring_access_checks ();

8048    return template_id;

8049 }

5.12.4.2.2.3.  Finish lookup class name

When get decl for the identifier , as indicated by the grammar, it must be an identifier or template-id. If argument typename_p is true, it means keyword typename has been seen. So invoke make_typename_type to resolve “typename CONTEXT::NAME" and return appropriate type.

 

cp_parser_class_name (continue)

 

11812    decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);

11813

11814     /* If this is a typename, create a TYPENAME_TYPE.  */

11815    if (typename_p && decl != error_mark_node)

11816    {

11817      decl = make_typename_type (scope, decl, /*complain=* /1);

11818      if (decl != error_mark_node)

11819        decl = TYPE_NAME (decl);

11820    }

11821

11822    /* Check to see that it is really the name of a class.  */

11823    if (TREE_CODE (decl) == TEMPLATE_ID_EXPR

11824        && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE

11825        && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))

11826        /* Situations like this:

11827

11828           template <typename T> struct A {

11829               typename T::template X<int>::I i;

11830           };

11831

11832           are problematic. Is `T::template X<int>' a class-name? The

11833           standard does not seem to be definitive, but there is no other

11834            valid interpretation of the following `::'. Therefore, those

11835           names are considered class-names.  */

11836      decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));

11837    else if (decl == error_mark_node

11838          || TREE_CODE (decl) != TYPE_DECL

11839           || !IS_AGGR_TYPE (TREE_TYPE (decl)))

11840    {

11841      cp_parser_error (parser, "expected class-name");

11842      return error_mark_node;

11843    }

11844

11845    return decl;

11846 }

 

Refer to maybe_get_template_decl_from_type_decl that invoked in cp_parser_template_id , it can better understand cp_parser_maybe_treat_template_as_class . Argument tag_name_p if true, decl indicates the class being defined in a class-head, or declared in an elaborated-type-specifier.

 

13901 static tree

13902 cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)              in parser.c

13903 {

13904   /* If the TEMPLATE_DECL is being declared as part of a class-head,

13905     the translation from TEMPLATE_DECL to TYPE_DECL occurs:

13906

13907        struct A {

13908          template <typename T> struct B;

13909        };

13910

13911        template <typename T> struct A::B {};

13912   

13913     Similarly, in a elaborated-type-specifier:

13914

13915        namespace N { struct X{}; }

13916

13917        struct A {

13918          template <typename T> friend struct N::X;

13919        };

13920

13921     However, if the DECL refers to a class type, and we are in

13922     the scope of the class, then the name lookup automatically

13923     finds the TYPE_DECL created by build_self_reference rather

13924     than a TEMPLATE_DECL. For example, in:

13925

13926        template <class T> struct S {

13927          S s;

13928        };

13929

13930     there is no need to handle such case.  */

13931

13932   if (DECL_CLASS_TEMPLATE_P (decl) && tag_name_p)

13933     return DECL_TEMPLATE_RESULT (decl);

13934

13935   return decl;

13936 }

 

The effect of the routine is if decl is a TEMPLATE_DECL that can be treated like a TYPE_DECL in the current context, returns the TYPE_DECL.

Below if name is a template class (by CLASSTYPE_IS_TEMPLATE) or a template instantiation or specialization (by CLASSTYPE_USE_TEMPLATE), a TMEPLATE_ID_EXPR is built. Its processing involves lookup_template_class which is a complex function and we will see it later with example.

 

2608 tree

2609 make_typename_type (tree context, tree name, tsubst_flags_t complain)               in decl.c

2610 {

2611    tree fullname;

2612

2613    if (name == error_mark_node

2614        || context == NULL_TREE

2615        || context == error_mark_node)

2616      return error_mark_node;

2617

2618    if (TYPE_P (name))

2619    {

2620      if (!(TYPE_LANG_SPECIFIC (name)

2621          && (CLASSTYPE_IS_TEMPLATE (name)

2622              || CLASSTYPE_USE_TEMPLATE (name))))

2623         name = TYPE_IDENTIFIER (name);

2624      else

2625         /* Create a TEMPLATE_ID_EXPR for the type.  */

2626         name = build_nt (TEMPLATE_ID_EXPR,

2627                       CLASSTYPE_TI_TEMPLATE (name),

2628                        CLASSTYPE_TI_ARGS (name));

2629    }

2630    else if (TREE_CODE (name) == TYPE_DECL)

2631      name = DECL_NAME (name);

2632

2633    fullname = name;

2634

2635    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)

2636    {

2637      name = TREE_OPERAND (name, 0);

2638      if (TREE_CODE (name) == TEMPLATE_DECL)

2639         name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);

2640    }

2641    if (TREE_CODE (name) == TEMPLATE_DECL)

2642    {

2643      error ("`%D' used without template parameters", name);

2644      return error_mark_node;

2645    }

2646    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);

2647    my_friendly_assert (TYPE_P (context), 20050905);

2648

2649    if (!dependent_type_p (context)

2650         || currently_open_class (context))

2651    {

2652      if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)

2653      {

2654          tree tmpl = NULL_TREE;

2655        if (IS_AGGR_TYPE (context))

2656            tmpl = lookup_field (context, name, 0, false);

2657        if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))

2658        {

2659          if (complain & tf_error)

2660             error ("no class template named `%#T' in `%#T'",

2661                  name, context);

2662          return error_mark_node;

2663        }

2664

2665        if (complain & tf_error)

2666            perform_or_defer_access_check (TYPE_BINFO (context), tmpl);

2667

2668        return lookup_template_class (tmpl,

2669                                  TREE_OPERAND (fullname, 1),

2670                                  NULL_TREE, context,

2671                                  /*entering_scope=*/ 0,

2672                                 tf_error | tf_warning | tf_user);

2673      }

2674      else

2675      {

2676        tree t;

2677

2678         if (!IS_AGGR_TYPE (context))

2679         {

2680           if (complain & tf_error)

2681            error ("no type named `%#T' in `%#T'", name, context);

2682            return error_mark_node;

2683         }

2684

2685         t = lookup_field (context, name, 0, true);

2686         if (t)

2687         {

2688           if (TREE_CODE (t) != TYPE_DECL)

2689          {

2690             if (complain & tf_error)

2691               error ("no type named `%#T' in `%#T'", name, context);

2692             return error_mark_node;

2693          }

2694

2695           if (complain & tf_error)

2696            perform_or_defer_access_check (TYPE_BINFO (context), t);

2697

2698           if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))

2699            t = TREE_TYPE (t);

2700      

2701          return t;

2702         }

2703      }

2704    }

2705

2706    /* If the CONTEXT is not a template type, then either the field is

2707      there now or its never going to be.  */

2708    if (!dependent_type_p (context))

2709    {

2710      if (complain & tf_error)

2711        error ("no type named `%#T' in `%#T'", name, context);

2712      return error_mark_node;

2713    }

2714

2715    return build_typename_type (context, name, fullname);

2716 }

 

And for expression “typename CONTEXT::NAME”, if CONTEXT is non-dependent, or is currently opened class, NAME is first looked up within the class by lookup_field .

 

1372 tree

1373 lookup_field (tree xbasetype, tree name, int protect, bool want_type)             in search.c

1374 {

1375    tree rval = lookup_member (xbasetype, name, protect, want_type);

1376   

1377    /* Ignore functions.  */

1378    if (rval && BASELINK_P (rval))

1379      return NULL_TREE;

1380

1381    return rval;

1382 }

 

See that argument want_type in invocation at line 2656 is false for template-id; and invocation at line 2685 is true for normal type. And want_type is true, indicates we only accept TYPE_DECL.

If nothing found and the scope is dependent, it must build a placeholder for the type. It is the node of TYPENAME_TYPE .

 

2566 static tree

2567 build_typename_type (tree context, tree name, tree fullname)                        in decl.c

2568 {

2569    tree t;

2570    tree d;

2571    void **e;

2572

2573    if (typename_htab == NULL)

2574    {

2575      typename_htab = htab_create_ggc (61, &typename_hash,

2576                                    &typename_compare, NULL);

2577    }

2578

2579    /* Build the TYPENAME_TYPE.  */

2580    t = make_aggr_type (TYPENAME_TYPE);

2581    TYPE_CONTEXT (t) = FROB_CONTEXT (context);

2582    TYPENAME_TYPE_FULLNAME (t) = fullname;

2583

2584    /* Build the corresponding TYPE_DECL.  */

2585    d = build_decl (TYPE_DECL, name, t);

2586    TYPE_NAME (TREE_TYPE (d)) = d;

2587    TYPE_STUB_DECL (TREE_TYPE (d)) = d;

2588    DECL_CONTEXT (d) = FROB_CONTEXT (context);

2589    DECL_ARTIFICIAL (d) = 1;

2590

2591    /* See if we already have this type.  */

2592    e = htab_find_slot (typename_htab , t, INSERT);

2593    if (*e)

2594      t = (tree) *e;

2595    else

2596      *e = t;

2597

2598    return t;

2599 }

 

Node of TYPENAME_TYPE represents structure “typename T::t”. In the node, its TYPE_CONTEXT is `T', TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.

Note that handling “typename T::t” here, ‘T’ has been resolved in previous step, it may be a template or template parameter, and with a subtree already built. So in fact “typename T::t” under different context ‘T’ stands for different structure. To ensure unique instance of such structure within the translation-unit, these nodes are stored within the hashtable of typename_htab .

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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、付费专栏及课程。

余额充值