Studying note of GCC-3.4.6 source (114)

5.12.4.      The second example

We have seen the procedure parser handles the template-class “SingleThreaded”, however, this example is quite simple in view of template declaration. Next we will see template declaration that derived from “SingleThreaded”, it can give us enlightment about how front-end processes template-template parameter, and inheritage. Here is the class-head we will hanlde:

    template

    <

        template <class > class ThreadingModel = DEFAULT_THREADING,

        std ::size_t chunkSize = DEFAULT_CHUNK_SIZE,

        std ::size_t maxSmallObjectSize = MAX_SMALL_OBJECT_SIZE

    >

    class SmallObject : public ThreadingModel<

        SmallObject<ThreadingModel, chunkSize, maxSmallObjectSize> >

In which DEFAULT_THREADING aliases to “::Loki::SingleThreaded”. The declaration obeys the rule:

template-declaration:

     export [opt] template-parameter-list-seq decl-specifier-seq [opt] init-declarator [opt] ;

5.12.4.1.              Parse template parameter list

5.12.4.1.1.        Template template parameter
5.12.4.1.1.1.  The parameter

Like previous example, it undergoes the calls stack of cp_parser_template_declaration à cp_parser_template_declaration_after_export à begin_template_parm_list (inserts scope of sk_template_parms), cp_parser_template_parameter_list à cp_parser_template_parameter à cp_parser_type_parameter . Following code of cp_parser_type_parameter is run for the example.

 

7720   static tree

7721   cp_parser_type_parameter (cp_parser* parser)                                            in parser.c

7722   {

7723     cp_token *token;

7724     tree parameter;

7725  

7726     /* Look for a keyword to tell us what kind of parameter this is.  */

7727     token = cp_parser_require (parser, CPP_KEYWORD,

7728                           "`class', `typename', or `template'");

7729     if (!token)

7730       return error_mark_node;

7731  

7732     switch (token->keyword)

7733     {

7734       case RID_CLASS:

7735       case RID_TYPENAME:

7736       {

            ...

7764       }

7765       break ;

7766  

7767        case RID_TEMPLATE:

7768       {

7769         tree parameter_list;

7770         tree identifier;

7771         tree default_argument;

7772  

7773         /* Look for the `<'.  */

7774         cp_parser_require (parser, CPP_LESS, "`<'");

7775         /* Parse the template-parameter-list.  */

7776         begin_template_parm_list ();

7777         parameter_list

7778            = cp_parser_template_parameter_list (parser);

7779         parameter_list = end_template_parm_list (parameter_list);

 

The first template parameter of our example is the template template parameter which begins with keyword template. This keyword template makes thing interesting now – a further scope of sk_template_parms is pushed in, and we will get following structure.


Figure 96 : before handling template template parameter

For the template template parameter, itself is a template declaration too. Here in the example, the template template parameter is: “template <class> class ThreadingModel”, and now the leading “template <” is consumed by parser. So in cp_parser_template_parameter (invoked by cp_parser_template_parameter_list at line 7778) following code is performed for the coming token “class”.

 

7654   static tree

7655   cp_parser_template_parameter (cp_parser* parser)                                      in parser.c

7656   {

7657     cp_token *token;

7658  

7659     /* Peek at the next token.  */

7660     token = cp_lexer_peek_token (parser->lexer);

7661     /* If it is `class' or `template', we have a type-parameter.  */

7662     if (token->keyword == RID_TEMPLATE)

7663       return cp_parser_type_parameter (parser);

7664     /* If it is `class' or `typename' we do not know yet whether it is a

7665       type parameter or a non-type parameter. Consider:

7666  

7667       template <typename T, typename T::X X> ...

7668  

7669       or:

7670      

7671       template <class C, class D*> ...

7672  

7673       Here, the first parameter is a type parameter, and the second is

7674       a non-type parameter. We can tell by looking at the token after

7675       the identifier -- if it is a `,', `=', or `>' then we have a type

7676       parameter.  */

7677     if (token->keyword == RID_TYPENAME || token->keyword == RID_CLASS)

7678     {

7679        /* Peek at the token after `class' or `typename'.  */

7680       token = cp_lexer_peek_nth_token (parser->lexer, 2);

7681       /* If it's an identifier, skip it.  */

7682       if (token->type == CPP_NAME)

7683         token = cp_lexer_peek_nth_token (parser->lexer, 3);

7684       /* Now, see if the token looks like the end of a template

7685         parameter.  */

7686       if (token->type == CPP_COMMA

7687          || token->type == CPP_EQ

7688          || token->type == CPP_GREATER)

7689         return cp_parser_type_parameter (parser);

7690     }

       

7703   }

 

Obviously, part “<class>” is the template parameter for the template template parameter; it is awkward-sounding, but shows the power of C++. Template can be nested to deep level – the standard defines that at least 12 levels should be allowed, in fact, every commercial compiler offers nesting level no less than 128.

For this template parameter “<class>”, cp_parser_type_parameter is recursed.

 

7720   static tree

7721   cp_parser_type_parameter (cp_parser* parser)                                            in parser.c

7722   {

7723     cp_token *token;

7724     tree parameter;

7725  

7726     /* Look for a keyword to tell us what kind of parameter this is.  */

7727     token = cp_parser_require (parser, CPP_KEYWORD,

7728                           "`class', `typename', or `template'");

7729     if (!token)

7730       return error_mark_node;

7731  

7732     switch (token->keyword)

7733     {

7734       case RID_CLASS:

7735       case RID_TYPENAME:

7736       {

7737         tree identifier;

7738         tree default_argument;

7739  

7740         /* If the next token is an identifier, then it names the

7741           parameter.  */

7742         if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))

7743           identifier = cp_parser_identifier (parser);

7744         else

7745           identifier = NULL_TREE;

7746  

7747         /* Create the parameter.  */

7748         parameter = finish_template_type_parm (class_type_node, identifier);

7749  

7750         /* If the next token is an `=', we have a default argument.  */

7751         if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))

7752          {

              ...

7757         }

7758         else

7759           default_argument = NULL_TREE;

7760  

7761           /* Create the combined representation of the parameter and the

7762           default argument.  */

7763         parameter = build_tree_list (default_argument, parameter);

7764       }

7765       break ;

         

7848     }

7849    

7850     return parameter;

7851   }

 

Above finish_template_type_parm creates a tree_list for the paramete; and further integrating into another tree_list at line 7763. Then parameter refers to nodes as below as the parameter is nameless and hasn’t default value.

Studying note of GCC-3.4.6 source (114)_第1张图片

Figure 97 : parameter node for template template parameter

Then back into cp_parser_template_parameter_list , process_template_parm packs template parameters. And note that it is the template parameter for the template template parameter! The argument next just refers to the node parameter in above figure.

 

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     {

          

2184     }

2185     else

2186       idx = 0;

2187  

2188     if (!is_type)

2189     {

         

2212     }

2213     else

2214     {

2215       tree t;

2216       parm = TREE_VALUE (parm);

2217        

2218       if (parm && TREE_CODE (parm) == TEMPLATE_DECL)

2219       {

            ...

2226       }

2227       else

2228       {

2229         t = make_aggr_type (TEMPLATE_TYPE_PARM);

2230         /* parm is either IDENTIFIER_NODE or NULL_TREE.  */

2231         decl = build_decl (TYPE_DECL, parm, t);

2232       }

2233          

2234       TYPE_NAME (t) = decl;

2235       TYPE_STUB_DECL (t) = decl;

2236       parm = decl;

2237       TEMPLATE_TYPE_PARM_INDEX (t)

2238           = build_template_parm_index (idx, processing_template_decl ,

2239                                    processing_template_decl ,

2240                                    decl, TREE_TYPE (parm));

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   }

 

Here begin_template_parm_list has been invoked twice so far, then processing_template_decl is 2. Note that TYPE_DECL of TEMPLATE_TPYE_PARM is nameless, so in pushdecl below, this TYPE_DECL is linked into names field of the relevant cxx_scope by add_decl_to_level .

 

566    tree

567    pushdecl (tree x)                                                                                     in name-lookup.c

568    {

569      tree t;

570      tree name;

571      int need_new_binding;

572   

573      timevar_push (TV_NAME_LOOKUP);

574   

575      need_new_binding = 1;

576   

577      if (DECL_TEMPLATE_PARM_P (x))

578        /* Template parameters have no context; they are not X::T even

579          when declared within a class or namespace.  */

580        ;

581      else

582      {

         

602      }

603   

604      name = DECL_NAME (x);

605      if (name)

606      {

         

1007     }

1008  

1009     if (need_new_binding)

1010       add_decl_to_level (x,

1011                       DECL_NAMESPACE_SCOPE_P (x)

1012                       ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))

1013                        : current_binding_level);

1014  

1015     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);

1016   }

 

Then back outer cp_parser_type_parameter from cp_parser_template_parameter_list , end_template_parm_list following prepares current_template_parms . And parameter_list returned is that in below figure.

(Click here for open )

Figure 98 : parameter list for template parameter of template template parameter

The following token must be “> class identifier [opt]”. By these tokens, the template template parameter comes into being.

 

cp_parser_type_parameter (continue)

 

7780           /* Look for the `>'.  */

7781         cp_parser_require (parser, CPP_GREATER, "`>'");

7782         /* Look for the `class' keyword.  */

7783         cp_parser_require_keyword (parser, RID_CLASS, "`class'");

7784         /* If the next token is an `=', then there is a

7785           default-argument. If the next token is a `>', we are at

7786           the end of the parameter-list. If the next token is a `,',

7787           then we are at the end of this parameter.  */

7788         if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)

7789            && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)

7790            && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))

7791         {

7792           identifier = cp_parser_identifier (parser);

7793           /* Treat invalid names as if the parameter were nameless. */

7794           if (identifier == error_mark_node)

7795             identifier = NULL_TREE;

7796         }

7797         else

7798           identifier = NULL_TREE;

7799  

7800         /* Create the template parameter.  */

7801         parameter = finish_template_template_parm (class_type_node ,

7802                                               identifier);

 

The template template parameter is a template declaration used in template parameter, it should be associated with a TEMPLATE_DECL to stand for this template declaration.

 

1943   tree

1944   finish_template_template_parm (tree aggr, tree identifier)                    in semantics.c

1945   {

1946     tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE);

1947     tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);

1948     DECL_TEMPLATE_PARMS (tmpl) = current_template_parms ;

1949     DECL_TEMPLATE_RESULT (tmpl) = decl;

1950     DECL_ARTIFICIAL (decl) = 1;

1951     end_template_decl ();

1952  

1953     my_friendly_assert (DECL_TEMPLATE_PARMS (tmpl), 20010110);

1954  

1955     return finish_template_type_parm (aggr, tmpl);

1956   }

 

As this template declaration is closed when the optional identifier is read, end_template_decl must be invoked to decrease processing_template_decl and jump out of the binding scope of the declaration (see it is the sk_template_parms). Further finish_template_type_parm packs the TEMPLATE_DECL into the template parameter for the host template declaraion. So before parsing the optional default value, we can get following figure.

( Click here for open )

Figure 99 : template template parameter created

你可能感兴趣的:(Studying note of GCC-3.4.6 source (114))