Studying note of GCC-3.4.6 source (130)
2010-12-13 17:06
351 查看
5.12.5.2.2.2.
Handling
the body
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
.
Handling
the body
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
.
相关文章推荐
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (139 - cont 2)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (142)
- Studying note of GCC-3.4.6 source (154)
- Studying note of GCC-3.4.6 source (166)
- Studying note of GCC-3.4.6 source (31)
- Studying note of GCC-3.4.6 source (169)
- Studying note of GCC-3.4.6 source (42)
- Studying note of GCC-3.4.6 source (47)
- Studying note of GCC-3.4.6 source (60)
- Studying note of GCC-3.4.6 source (62)
- Studying note of GCC-3.4.6 source (78)
- Studying note of GCC-3.4.6 source (110)
- Studying note of GCC-3.4.6 source (134)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (13)
- Studying note of GCC-3.4.6 source (147)
- Studying note of GCC-3.4.6 source (26 cont1)