您的位置:首页 > 其它

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

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: