The second statement is template-declaration, and the abbreviate syntax tree is shown in below. The first syntax is the declaration of class template, and the second one is the declaration of function template. Now we are defining the template class.
template-declaration
├ export [opt] template < template-parameter-list> decl-specific-seq [opt] init-declarator [opt];
Ⅼ export [opt] template < template- parameter -list> function-definition
In cp_parser_declaration , following code segement handles template related definition.
cp_parser_declaration (continue)
6306 /* If the next token is `template', then we have either a template
6307 declaration, an explicit instantiation, or an explicit
6308 specialization. */
6309 else if (token1.keyword == RID_TEMPLATE)
6310 {
6311 /* `template <>' indicates a template specialization. */
6312 if (token2.type == CPP_LESS
6313 && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER)
6314 cp_parser_explicit_specialization (parser);
6315 /* `template <' indicates a template declaration. */
6316 else if (token2.type == CPP_LESS)
6317 cp_parser_template_declaration (parser, /*member_p=*/ false);
6318 /* Anything else must be an explicit instantiation. */
6319 else
6320 cp_parser_explicit_instantiation (parser);
6321 }
6322 /* If the next token is `export', then we have a template
6323 declaration. */
6324 else if (token1.keyword == RID_EXPORT)
6325 cp_parser_template_declaration (parser, /*member_p=*/ false);
6326 /* If the next token is `extern', 'static' or 'inline' and the one
6327 after that is `template', we have a GNU extended explicit
6328 instantiation directive. */
6329 else if (cp_parser_allow_gnu_extensions_p (parser)
6330 && (token1.keyword == RID_EXTERN
6331 || token1.keyword == RID_STATIC
6332 || token1.keyword == RID_INLINE)
6333 && token2.keyword == RID_TEMPLATE)
6334 cp_parser_explicit_instantiation (parser);
When seeing the heading tokens: “template <class Host> class SingleThreaded”, parser can know it’s a template declaration at line 6316, and invokes the handler.
7593 static void
7594 cp_parser_template_declaration (cp_parser* parser, bool member_p) in parser.c
7595 {
7596 /* Check for `export'. */
7597 if (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT))
7598 {
7599 /* Consume the `export' token. */
7600 cp_lexer_consume_token (parser->lexer);
7601 /* Warn that we do not support `export'. */
7602 warning ("keyword `export' not implemented, and will be ignored");
7603 }
7604
7605 cp_parser_template_declaration_after_export (parser, member_p);
7606 }
Keyword export is used in separation compilation model. With the separation compilation model, the class template definition and the definitions of its inline member functions are placed in a header file, whereas the definitions of the non-inline member functions and static data members are placed in a program text file. With this model, the definitions for a class template and its members are organized in the same way we organize the definitions of nontemplate classes and their members. But this version can’t support it.
14420 static void
14421 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) in parser.c
14422 {
14423 tree decl = NULL_TREE;
14424 tree parameter_list;
14425 bool friend_p = false;
14426
14427 /* Look for the `template' keyword. */
14428 if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
14429 return ;
14430
14431 /* And the `<'. */
14432 if (!cp_parser_require (parser, CPP_LESS, "`<'"))
14433 return ;
14434
14435 /* If the next token is `>', then we have an invalid
14436 specialization. Rather than complain about an invalid template
14437 parameter, issue an error message here. */
14438 if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
14439 {
14440 cp_parser_error (parser, "invalid explicit specialization");
14441 begin_specialization ();
14442 parameter_list = NULL_TREE;
14443 }
14444 else
14445 {
14446 /* Parse the template parameters. */
14447 begin_template_parm_list ();
14448 parameter_list = cp_parser_template_parameter_list (parser);
14449 parameter_list = end_template_parm_list (parameter_list);
14450 }
As we know that declaration like class T in template parameter list is not a normal class declaration, but somewhat a place-holder, then during template instantiation it will be replaced by specified type appropriately. It is important to separate this type declaration from current binding scope and place it into special ones (i.e, sk_template_parms ).
598 void
599 begin_template_parm_list (void) in pt.c
600 {
601 /* We use a non-tag-transparent scope here, which causes pushtag to
602 put tags in this scope, rather than in the enclosing class or
603 namespace scope. This is the right thing, since we want
604 TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a
605 global template class, push_template_decl handles putting the
606 TEMPLATE_DECL into top-level scope. For a nested template class,
607 e.g.:
608
609 template <class T> struct S1 {
610 template <class T> struct S2 {};
611 };
612
613 pushtag contains special code to call pushdecl_with_scope on the
614 TEMPLATE_DECL for S2. */
615 begin_scope (sk_template_parms, NULL);
616 ++processing_template_decl ;
617 ++processing_template_parmlist ;
618 note_template_header (0);
619 }
Above processing_template_decl refers to x_processing_template_decl field of scope_chain . It and global variable processing_template_parmlist records the depth of template declaration the template parameter list being processed.
687 static void
688 note_template_header (int specialization) in pt.c
689 {
690 processing_specialization = specialization;
691 template_header_count ++;
692 }
The layout after pushing the special sk_template_parms scope is shown as below.
Figure 47 : brief layout after pushing sk_template_parm
Here processing_specialization refers the slot x_processing_specialization of scope_chain , it is nonzero if template specification is found (i.e, seeing template <> ). And global variable template_header_count if nonzero indicates seeing template header (i.e, template ).
From the abbreviate syntax tree below, surprising to see the complexity it may be.
template < template-parameter-list >
├ template-parameter
Ⅼ template-parameter-list , template-parameter
├ type-parameter
| ├ class identifier [opt]
| ├ class identifier [opt] = type-id
| ├ typename identifier [opt]
| ├ template < template-parameter-list > class identifer [opt]
| Ⅼ template < template-parameter-list > class identifer [opt] = id-expression
|
Ⅼ parameter-declaration
├ decl-specifier-seq declarator
├ decl-specifier-seq declarator = assignment-expression
├ decl-specifier-seq abstract-declarator [opt]
Ⅼ decl-specifier-seq abstract-declarator [opt] = assignment-expression
As the parameter list can contain any number of parameter, token of comma drives the WHILE loop in below at line 7622.
7617 static tree
7618 cp_parser_template_parameter_list (cp_parser* parser) in parser.c
7619 {
7620 tree parameter_list = NULL_TREE;
7621
7622 while (true)
7623 {
7624 tree parameter;
7625 cp_token *token;
7626
7627 /* Parse the template-parameter. */
7628 parameter = cp_parser_template_parameter (parser);
7629 /* Add it to the list. */
7630 parameter_list = process_template_parm (parameter_list,
7631 parameter);
7632
7633 /* Peek at the next token. */
7634 token = cp_lexer_peek_token (parser->lexer);
7635 /* If it's not a `,', we're done. */
7636 if (token->type != CPP_COMMA)
7637 break ;
7638 /* Otherwise, consume the `,' token. */
7639 cp_lexer_consume_token (parser->lexer);
7640 }
7641
7642 return parameter_list;
7643 }
In the above syntax tree, type-parameter of template-parameter constructs type parameter, while parameter-declaration of template-parameter constructs non-type parameter. They contain very different nonterminals, however they still possible have common header for instance:
template < typename T, typename T::X X>, first T is type parameter, and second T::X is the non-type parameter.
Also, template <class C, class D*>, C is type parameter, and D* is the non-type one.
The related function needs handle these two variant carefully.