Before going deeper into the function-body, which forms a new binding scope of block-scope, any pendding accessibility checkings should be performed to find out the illegal visit early.
cp_parser_function_definition_from_specifiers_and_declarator (continue)
14329 /* If there were names looked up in the decl-specifier-seq that we
14330 did not check, check them now. We must wait until we are in the
14331 scope of the function to perform the checks, since the function
14332 might be a friend. */
14333 perform_deferred_access_checks ();
14334
14335 if (!success_p)
14336 {
14337 /* If begin_function_definition didn't like the definition, skip
14338 the entire function. */
14339 error ("invalid function declaration");
14340 cp_parser_skip_to_end_of_block_or_statement (parser);
14341 fn = error_mark_node;
14342 }
14343 else
14344 fn = cp_parser_function_definition_after_declarator (parser,
14345 /*inline_p=*/ false);
14346
14347 return fn;
14348 }
We have seen cp_parser_function_definition_after_declarator in section 5.12.3.2.1.2.1.1.Parse function body . In it, cp_parser_ctor_initializer_opt_and_function_body parses the function-body and possible initializer for constructor. And in this function, begin_function_body prepares the root of sub-tree for the compound-statement, and the enclosing scope. After that, the relevant part of the intermediate tree now looks like below one.
(Click here for open )
And cp_parser_function_body handles the body which is a compound-statement.
11460 static void
11461 cp_parser_function_body (cp_parser *parser) in parser.c
11462 {
11463 cp_parser_compound_statement (parser, false);
11464 }
5651 static tree
5652 cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
5653 {
5654 tree compound_stmt;
5655
5656 /* Consume the `{'. */
5657 if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
5658 return error_mark_node;
5659 /* Begin the compound-statement. */
5660 compound_stmt = begin_compound_stmt (/*has_no_scope=*/ false);
5661 /* Parse an (optional) statement-seq. */
5662 cp_parser_statement_seq_opt (parser, in_statement_expr_p);
5663 /* Finish the compound-statement. */
5664 finish_compound_stmt (compound_stmt);
5665 /* Consume the `}'. */
5666 cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
5667
5668 return compound_stmt;
5669 }
Another enclosing scope is created before handling the tokens following “{“, it is because former block-scope is built for the optional constructor initializer, and the one created here is really for the body.
(Click here for open )
5677 static void
5678 cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p) in parser.c
5679 {
5680 /* Scan statements until there aren't any more. */
5681 while (true)
5682 {
5683 /* If we're looking at a `}', then we've run out of statements. */
5684 if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
5685 || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
5686 break ;
5687
5688 /* Parse the statement. */
5689 cp_parser_statement (parser, in_statement_expr_p);
5690 }
5691 }
Deep into the callstack: cp_parser_statement à cp_parser_declaration_statement à cp_parser_block_declaration à cp_parser_simple_declaration , cp_parser_decl_specifier_seq parses the type-specifier for the first declaration by cp_parser_type_specifier à cp_parser_simple_type_specifier à cp_parser_type_name à cp_parser_class_name to find out the template-id of “SmallObject<>”.
5425 static void
5426 cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) in parser.c
5427 {
5428 tree statement;
5429 cp_token *token;
5430 int statement_line_number;
5431
5432 /* There is no statement yet. */
5433 statement = NULL_TREE;
5434 /* Peek at the next token. */
5435 token = cp_lexer_peek_token (parser->lexer);
5436 /* Remember the line number of the first token in the statement. */
5437 statement_line_number = token->location.line;
5438 /* If this is a keyword, then that will often determine what kind of
5439 statement we have. */
5440 if (token->type == CPP_KEYWORD)
5441 {
…
5479 }
5480 else if (token->type == CPP_NAME)
5481 {
5482 /* If the next token is a `:', then we are looking at a
5483 labeled-statement. */
5484 token = cp_lexer_peek_nth_token (parser->lexer, 2);
5485 if (token->type == CPP_COLON)
5486 statement = cp_parser_labeled_statement (parser, in_statement_expr_p);
5487 }
5488 /* Anything that starts with a `{' must be a compound-statement. */
5489 else if (token->type == CPP_OPEN_BRACE)
5490 statement = cp_parser_compound_statement (parser, false);
5491
5492 /* Everything else must be a declaration-statement or an
5493 expression-statement. Try for the declaration-statement
5494 first, unless we are looking at a `;', in which case we know that
5495 we have an expression-statement. */
5496 if (!statement)
5497 {
5498 if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
5499 {
5500 cp_parser_parse_tentatively (parser);
5501 /* Try to parse the declaration-statement. */
5502 cp_parser_declaration_statement (parser);
5503 /* If that worked, we're done. */
5504 if (cp_parser_parse_definitely (parser))
5505 return ;
5506 }
5507 /* Look for an expression-statement instead. */
5508 statement = cp_parser_expression_statement (parser, in_statement_expr_p);
5509 }
5510
5511 /* Set the line number for the statement. */
5512 if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
5513 STMT_LINENO (statement) = statement_line_number;
5514 }
A declaration statement introduces one or more new identifiers into a block; it has the form
declaration-statement: block-declaration
If an identifier introduced by a declaration was previously declared in an outer block, the outer declaration is hidden for the remainder of the block, after which it resumes its force.
Variables with automatic storage duration are initialized each time their declaration-statement is executed. Variables with automatic storage duration declared in the block are destroyed on exit from the block.
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type and is declared without an initializer. For example:
void f() {
// ...
goto lx; // ill-formed: jump into scope of a
// ...
ly:
X a = 1;
// ...
lx:
goto ly; // OK, jump implies destructor call for a followed by construction
// again immediately following label ly
}
The zero-initialization of all local objects with static storage duration is performed before any other initialization takes place. A local object of POD type with static storage duration initialized with constant-expressions is initialized before its block is first entered. An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope. Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control re-enters the declaration (recursively) while the object is being initialized, the behavior is undefined. For example:
int foo(int i) {
static int s = foo(2*i); // recursive call – undefined
return i+1;
}
The destructor for a local object with static storage duration will be executed if and only if the variable was constructed.
6144 static void
6145 cp_parser_declaration_statement (cp_parser* parser) in parser.c
6146 {
6147 /* Parse the block-declaration. */
6148 cp_parser_block_declaration (parser, /*statement_p=*/ true);
6149
6150 /* Finish off the statement. */
6151 finish_stmt ();
6152 }
For “SmallObject<> object_;”, it is parsed following rule of block-declaration again.With call stack: cp_parser_block_declaration à cp_parser_simple_declaration à cp_parser_type_specifier à cp_parser_simple_type_specifier à cp_parser_type_name à cp_parser_class_name , template-id “SmallObject” is recognized.
5.12.5.2.2.2.1. Template instantation
5.12.5.2.2.2.1.1. The template-id
In this invocation of cp_parser_class_name , the arguments typename_keyword_p , template_keyword_p , type_p , class_head_p , and is_declaration are false; and check_dependency_p is true. The detail of template-id lookup, refers to section 5.412.4.2.2.2. Template-id .
In cp_parser_template_id , if the template is a class template or a template template parameter, it will call finish_template_type to finish the processing. For our example, in finish_template_type , lookup_template_class has arguments in_decl and context of NULL, arglist of the template argument-list which is NULL too, dl of the node of TEMPLATE_DECL, and entering_scope of nonzero which means entering the scope of template-id indicated.
4133 tree
4134 lookup_template_class (tree d1, in pt.c
4135 tree arglist,
4136 tree in_decl,
4137 tree context,
4138 int entering_scope,
4139 tsubst_flags_t complain)
4140 {
4141 tree template = NULL_TREE, parmlist;
4142 tree t;
4143
4144 timevar_push (TV_NAME_LOOKUP);
4145
4146 if (TREE_CODE (d1) == IDENTIFIER_NODE)
4147 {
…
4162 }
4163 else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
4164 {
…
4177 }
4178 else if (TREE_CODE (d1) == ENUMERAL_TYPE
4179 || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
4180 {
…
4183 }
4184 else if (TREE_CODE (d1) == TEMPLATE_DECL
4185 && TREE_CODE (DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
4186 {
4187 template = d1;
4188 d1 = DECL_NAME (template);
4189 context = DECL_CONTEXT (template);
4190 }
…
4219 complain &= ~tf_user;
4220
4221 if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
4222 {
…
4259 }
4260 else
4261 {
4262 tree template_type = TREE_TYPE (template);
4263 tree gen_tmpl;
4264 tree type_decl;
4265 tree found = NULL_TREE;
4266 tree *tp;
4267 int arg_depth;
4268 int parm_depth;
4269 int is_partial_instantiation;
4270
4271 gen_tmpl = most_general_template (template);
4272 parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
4273 parm_depth = TMPL_PARMS_DEPTH (parmlist);
4274 arg_depth = TMPL_ARGS_DEPTH (arglist);
4275
4276 if (arg_depth == 1 && parm_depth > 1)
4277 {
…
4294 }
4295
4296 /* Now we should have enough arguments. */
4297 my_friendly_assert (parm_depth == arg_depth, 0);
4298
4299 /* From here on, we're only interested in the most general
4300 template. */
4301 template = gen_tmpl;
4302
4303 /* Calculate the BOUND_ARGS. These will be the args that are
4304 actually tsubst'd into the definition to create the
4305 instantiation. */
4306 if (parm_depth > 1)
4307 {
…
4344 }
4345 else
4346 arglist
4347 = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
4348 INNERMOST_TEMPLATE_ARGS (arglist),
4349 template,
4350 complain, /*require_all_args=*/ 1);
4351
4352 if (arglist == error_mark_node)
4353 /* We were unable to bind the arguments. */
4354 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
5.12.5.2.2.2.1.1.1. Replace the first default arguments
As arglist is NULL, at line 4348 INNERMOST_TEMPLATE_ARGS returns NULL as result. And template itself is the most general form, so INNERMOST_TEMPLATE_PARMS returns the TREE_VEC in below figure for the parameters.
(Click here for open )
3805 static tree
3806 coerce_template_parms (tree parms, in pt.c
3807 tree args,
3808 tree in_decl,
3809 tsubst_flags_t complain,
3810 int require_all_arguments)
3811 {
3812 int nparms, nargs, i, lost = 0;
3813 tree inner_args;
3814 tree new_args;
3815 tree new_inner_args;
3816
3817 inner_args = INNERMOST_TEMPLATE_ARGS (args);
3818 nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
3819 nparms = TREE_VEC_LENGTH (parms);
3820
3821 if (nargs > nparms
3822 || (nargs < nparms
3823 && require_all_arguments
3824 && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
3825 {
3826 if (complain & tf_error)
3827 {
3828 error ("wrong number of template arguments (%d, should be %d)",
3829 nargs, nparms);
3830
3831 if (in_decl)
3832 cp_error_at ("provided for `%D'", in_decl);
3833 }
3834
3835 return error_mark_node;
3836 }
3837
3838 new_inner_args = make_tree_vec (nparms);
3839 new_args = add_outermost_template_args (args, new_inner_args);
3840 for (i = 0; i < nparms; i++)
3841 {
3842 tree arg;
3843 tree parm;
3844
3845 /* Get the Ith template parameter. */
3846 parm = TREE_VEC_ELT (parms, i);
3847
3848 /* Calculate the Ith argument. */
3849 if (i < nargs)
3850 arg = TREE_VEC_ELT (inner_args, i);
3851 else if (require_all_arguments)
3852 /* There must be a default arg in this case. */
3853 arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
3854 complain, in_decl);
3855 else
3856 break ;
3857
3858 my_friendly_assert (arg, 20030727);
3859 if (arg == error_mark_node)
3860 error ("template argument %d is invalid", i + 1);
3861 else
3862 arg = convert_template_argument (TREE_VALUE (parm),
3863 arg, new_args, complain, i,
3864 i n_decl);
3865
3866 if (arg == error_mark_node)
3867 lost++;
3868 TREE_VEC_ELT (new_inner_args, i) = arg;
3869 }
3870
3871 if (lost)
3872 return error_mark_node;
3873
3874 return new_inner_args;
3875 }
Above at line 3839, as args is NULL, add_outermost_template_args does nothing but returns new_inner_args . In above figure, we see that TREE_PURPOSE field (the default argument) of first parameter is the TMEPLATE_DECL of “SingleThreaded”. Then next is the arguments replacement.
5700 static tree
5701 tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl) in pt.c
5702 {
5703 tree r;
5704
5705 if (!t)
5706 r = t;
5707 else if (TYPE_P (t))
5708 r = tsubst (t, args, complain, in_decl);
5709 else
5710 {
5711 r = tsubst_expr (t, args, complain, in_decl);
5712
5713 if (!uses_template_parms (r))
5714 {
5715 /* Sometimes, one of the args was an expression involving a
5716 template constant parameter, like N - 1. Now that we've
5717 tsubst'd, we might have something like 2 - 1. This will
5718 confuse lookup_template_class, so we do constant folding
5719 here. We have to unset processing_template_decl, to fool
5720 tsubst_copy_and_build() into building an actual tree. */
5721
5722 /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
5723 as simple as it's going to get, and trying to reprocess
5724 the trees will break. Once tsubst_expr et al DTRT for
5725 non-dependent exprs, this code can go away, as the type
5726 will always be set. */
5727 if (!TREE_TYPE (r))
5728 {
5729 int saved_processing_template_decl = processing_template_decl;
5730 processing_template_decl = 0;
5731 r = tsubst_copy_and_build (r, /*args=*/ NULL_TREE,
5732 tf_error, /*in_decl=*/ NULL_TREE,
5733 /*function_p=*/ false);
5734 processing_template_decl = saved_processing_template_decl;
5735 }
5736 r = fold (r);
5737 }
5738 }
5739 return r;
5740 }
Being a node satisfying DECL_P, tsubst_expr takes the job.
7822 static tree
7823 tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) in pt.c
7824 {
7825 tree stmt, tmp;
7826 tsubst_flags_t stmt_expr
7827 = complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body);
7828
7829 complain ^= stmt_expr;
7830 if (t == NULL_TREE || t == error_mark_node)
7831 return t;
7832
7833 if (!STATEMENT_CODE_P (TREE_CODE (t)))
7834 return tsubst_copy_and_build (t, args, complain, in_decl,
7835 /*function_p=*/ false);
…
8156 }
STATEMENT_CODE_P above returns nonzero if the code of the node indicates that the node is one of the statements (of course, TEMPLATE_DECL is not qualified; see section 4.3.1.1. stmt_codes for reference).
8180 tree
8181 tsubst_copy_and_build (tree t, in pt.c
8182 tree args,
8183 tsubst_flags_t complain,
8184 tree in_decl,
8185 bool function_p)
8186 {
8187 #define RECUR(NODE) /
8188 tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/ false)
8189
8190 tree op1;
8191
8192 if (t == NULL_TREE || t == error_mark_node)
8193 return t;
8194
8195 switch (TREE_CODE (t))
8196 {
…
8693 default :
8694 return tsubst_copy (t, args, complain, in_decl);
8695 }
8696
8697 #undef RECUR
8698 }
TEMPLATE_DECL doesn’t require special treatment in tsubst_copy_and_build (just “copy” is enough).
7449 static tree
7450 tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) in pt.c
7451 {
7452 enum tree_code code;
7453 tree r;
7454
7455 if (t == NULL_TREE || t == error_mark_node)
7456 return t;
7457
7458 code = TREE_CODE (t);
7459
7460 switch (code)
7461 {
…
7542 case TEMPLATE_DECL:
7543 if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
7544 return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
7545 args, complain, in_decl);
7546 else if (is_member_template (t))
7547 return tsubst (t, args, complain, in_decl);
7548 else if (DECL_CLASS_SCOPE_P (t)
7549 && uses_template_parms (DECL_CONTEXT (t)))
7550 {
7551 /* Template template argument like the following example need
7552 special treatment:
7553
7554 template <template <class> class TT> struct C {};
7555 template <class T> struct D {
7556 template <class U> struct E {};
7557 C<E> c; // #1
7558 };
7559 D<int> d; // #2
7560
7561 We are processing the template argument `E' in #1 for
7562 the template instantiation #2. Originally, `E' is a
7563 TEMPLATE_DECL with `D<T>' as its DECL_CONTEXT. Now we
7564 have to substitute this with one having context `D<int>'. */
7565
7566 tree context = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
7567 return lookup_field (context, DECL_NAME(t), 0, false);
7568 }
7569 else
7570 /* Ordinary template template argument. */
7571 return t;
…
7816 }
7817 }
Not defined in template parameter-list, DECL_TEMPLATE_TEMPLATE_PARM_P returns zero for “SingleThreaded”; nor is it a member template; and the context (enclosing scope) of “SingleThreaded” is the namespace of “Loki” which of course is not type-dependent or value-dependent (so uses_template_parms returns false); so the node of TEMPLATE_DECL is just returned at line 7571.
After returning back tsubst_template_arg , TEMPLATE_DECL which isn’t template template parameter causes uses_template_parms at line 5713 returns false, and it skips IF block at line 5727 as type field is not NULL. Further fold following does nothing as no constant can be folded but just returns the TEMPLATE_DECL.
After returning the default argument, it checks if adjustment is needed and possible. Node of TEMPLATE_DECL in below figure is pointed by parm , which comes from template parameter definition.
(Click here for open )
In below figure, node of TEMPLATE_DECL is referred by arg , which comes from the definition of “SingleThreaded”.
(Click here for open )
3636 static tree
3637 convert_template_argument (tree parm, in pt.c
3638 tree arg,
3639 tree args,
3640 tsubst_flags_t complain,
3641 int i,
3642 tree in_decl)
3643 {
3644 tree val;
3645 tree inner_args;
3646 int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
3647
3648 inner_args = INNERMOST_TEMPLATE_ARGS (args);
3649
3650 requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
3651 requires_type = (TREE_CODE (parm) == TYPE_DECL
3652 || requires_tmpl_type);
3653
3654 is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
3655 && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
3656 || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
3657 || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
3658
3659 if (is_tmpl_type
3660 && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
3661 || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
3662 arg = TYPE_STUB_DECL (arg);
3663
3664 is_type = TYPE_P (arg) || is_tmpl_type;
…
3722 if (is_type)
3723 {
3724 if (requires_tmpl_type)
3725 {
3726 if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
3727 /* The number of argument required is not known yet.
3728 Just accept it for now. */
3729 val = TREE_TYPE (arg);
3730 else
3731 {
3732 tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
3733 tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
3734
3735 if (coerce_template_template_parms (parmparm, argparm,
3736 complain, in_decl,
3737 inner_args))
3738 {
3739 val = arg;
3740
3741 /* TEMPLATE_TEMPLATE_PARM node is preferred over
3742 TEMPLATE_DECL. */
3743 if (val != error_mark_node
3744 && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
3745 val = TREE_TYPE (val);
3746 }
3747 else
3748 {
…
3757 }
3758 }
3759 }
3760 else
3761 val = groktypename (arg);
3762 }
3763 else
3764 {
…
3790 }
3791
3792 return val;
3793 }
Clearly, at line 3732, parmparm and argparm refer to the nodes of TREE_VEC respectively in figure they belong to. Nothing is done in coerce_template_template_parms , and 1 is returned. So arg is returned by convert_template_argument . Then it is set in first element of new_inner_args in coerce_template_parms .