Studying note of GCC-3.4.6 source (109)
2010-10-11 11:39
260 查看
5.12.3.2.1.2.1.2.
Parse
function body
For the keyword “return” seen at line 14368 which follows “)”,
refers to section Build
nodes for method
for detail.
14356
static
tree
14357
cp_parser_function_definition_after_declarator
(cp_parser* parser,
in parser.c
14358
bool inline_p)
14359
{
14360
tree fn;
14361
bool ctor_initializer_p =
false;
14362
bool
saved_in_unbraced_linkage_specification_p;
14363
unsigned
saved_num_template_parameter_lists;
14364
14365
/*
If the next token is `return', then the code may be trying to
14366
make
use of the "named return value" extension that G++ used to
14367
support.
*/
14368
if (cp_lexer_next_token_is_keyword
(parser->lexer, RID_RETURN))
14369
{
14370
/*
Consume the `return' keyword.
*/
14371
cp_lexer_consume_token
(parser->lexer);
14372
/*
Look for the identifier that indicates what value is to be
14373
returned.
*/
14374
cp_parser_identifier
(parser);
14375
/*
Issue an error message.
*/
14376
error ("named return
values are no longer supported");
14377
/*
Skip tokens until we reach the start of the function body.
*/
14378
while
(cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
14379
&&
cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
14380
cp_lexer_consume_token
(parser->lexer);
14381
}
14382
/*
The `extern' in `extern "C" void f () { ... }' does not apply to
14383
anything declared inside `f'.
*/
14384
saved_in_unbraced_linkage_specification_p
14385
=
parser->in_unbraced_linkage_specification_p;
14386
parser->in_unbraced_linkage_specification_p
= false;
14387
/*
Inside the function, surrounding template-parameter-lists do not
14388
apply.
*/
14389
saved_num_template_parameter_lists
14390
=
parser->num_template_parameter_lists;
14391
parser->num_template_parameter_lists
= 0;
14392
/*
If the next token is `try', then we are looking at a
14393
function-try-block.
*/
14394
if (cp_lexer_next_token_is_keyword
(parser->lexer, RID_TRY))
14395
ctor_initializer_p =
cp_parser_function_try_block (parser);
14396
/*
A function-try-block includes the function-body, so we only do
14397
this
next part if we're not processing a function-try-block.
*/
14398
else
14399
ctor_initializer_p
14400
= cp_parser_ctor_initializer_opt_and_function_body
(parser);
14401
14402
/*
Finish the function.
*/
14403
fn = finish_function
((ctor_initializer_p ? 1 : 0) |
14404
(inline_p ?
2 : 0));
14405
/*
Generate code for it, if necessary.
*/
14406
expand_or_defer_fn (fn);
14407
/*
Restore the saved values.
*/
14408
parser->in_unbraced_linkage_specification_p
14409
= saved_in_unbraced_linkage_specification_p;
14410
parser->num_template_parameter_lists
14411
=
saved_num_template_parameter_lists;
14412
14413
return
fn;
14414
}
5.12.3.2.1.2.1.2.1.
Preparation
Though our example method contains an empty function body, but
handling empty function body still embodies rather complex procedure.
11469
static
bool
11470
cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *parser)
in parser.c
11471
{
11472
tree body;
11473
bool ctor_initializer_p;
11474
11475
/*
Begin the function body.
*/
11476
body = begin_function_body
();
11477
/*
Parse the optional ctor-initializer.
*/
11478
ctor_initializer_p =
cp_parser_ctor_initializer_opt (parser);
11479
/*
Parse the function-body.
*/
11480
cp_parser_function_body
(parser);
11481
/*
Finish the function body.
*/
11482
finish_function_body
(body);
11483
11484
return
ctor_initializer_p;
11485
}
The function body is a compound statement itself, which has
following rule:
compound-statement:
{ statement-seq [opt] }
The statement-seq is enclosed the pair of brace which forms a scope
that separates this statement-seq from outside. So before really handling
function body it needs some preparation.
10756
tree
10757
begin_function_body
(void)
in decl.c
10758
{
10759
tree stmt;
10760
10761
if (processing_template_decl
)
10762
/*
Do nothing now.
*/;
10763
else
10764
/*
Always keep the BLOCK node associated with the outermost pair of
10765
curly braces of a function. These are needed for correct
10766
operation of dwarfout.c.
*/
10767
keep_next_level (true);
10768
10769
stmt = begin_compound_stmt
(/*has_no_scope=*/
false);
10770
COMPOUND_STMT_BODY_BLOCK
(stmt) = 1;
10771
10772
if (processing_template_decl
)
10773
/*
Do nothing now.
*/;
10774
else if (DECL_CONSTRUCTOR_P
(current_function_decl
))
10775
begin_constructor_body ();
10776
else if (DECL_DESTRUCTOR_P (current_function_decl
))
10777
begin_destructor_body ();
10778
10779
return
stmt;
10780
}
See that argument has_no_scope
is false for the invocation, which
means the compound statement defines a scope.
998
tree
999
begin_compound_stmt
(bool has_no_scope)
in semantics.c
1000
{
1001
tree r;
1002
int is_try = 0;
1003
1004
r = build_stmt
(COMPOUND_STMT, NULL_TREE);
1005
1006
if (last_tree &&
TREE_CODE (last_tree) == TRY_BLOCK)
1007
is_try = 1;
1008
1009
add_stmt
(r);
1010
if (has_no_scope)
1011
COMPOUND_STMT_NO_SCOPE (r)
= 1;
1012
1013
last_expr_type = NULL_TREE;
1014
1015
if (!has_no_scope)
1016
do_pushlevel
(is_try ? sk_try : sk_block);
1017
else
1018
/* Normally, we try hard to keep the BLOCK for
a
1019
statement-expression. But, if it's a statement-expression with
1020
a
scopeless block, there's nothing to keep, and we don't want
1021
to
accidentally keep a block *inside* the scopeless block.
*/
1022
keep_next_level (false);
1023
1024
return
r;
1025
}
In intermediate tree, brace and parethensis can’t be present. To mark
all statements within the compound statement, a node of COMPOUND_STMT is
created being the head of statement list. At line 84, last_expr_filename
is updated as input_filename
in begin_stmt_tree
.
And if current input file is not the same as that current function belonged,
node of FILE_STMT is created to tell the difference.
81
tree
82
add_stmt
(tree t)
in c-semantics.c
83
{
84
if (input_filename !=
last_expr_filename)
85
{
86
/*
If the filename has changed, also add in a FILE_STMT. Do a string
87
compare first, though, as it might be an
equivalent string.
*/
88
int add = (strcmp
(input_filename, last_expr_filename) != 0);
89
last_expr_filename =
input_filename;
90
if (add)
91
{
92
tree pos = build_nt
(FILE_STMT,
get_identifier
(input_filename));
93
add_stmt (pos);
94
}
95
}
96
97
/*
Add T to the statement-tree.
*/
98
TREE_CHAIN (last_tree) = t;
99
last_tree = t;
100
101
/*
When we expand a statement-tree, we must know whether or not the
102
statements are full-expressions. We record that fact here.
*/
103
STMT_IS_FULL_EXPR_P
(last_tree) = stmts_are_full_exprs_p
();
104
105
return
t;
106
}
Notice that the statement is added at tail of the statement-list,
however, field saved_tree
of the FUNCTION_DECL still refers to the head of the list. Routine stmts_are_full_exprs_p
returns true if the current statement is a full expression (i.e. temporaries
created during that statement should be destroyed at the end of the statement).
Field stmts_are_full_exprs_p
is set as 1 at line 11299 in cxx_push_function_context
.
306
int
307
stmts_are_full_exprs_p
(void)
in semantics.c
308
{
309
return
current_stmt_tree
()->stmts_are_full_exprs_p;
310
}
Then if the compound statement defines a scope, a new scope should
be pushed as sk_block or try_block.
364
void
365
do_pushlevel
(scope_kind sk)
in semantics.c
366
{
367
if (stmts_are_full_exprs_p
())
368
{
369
if (!processing_template_decl
)
370
add_scope_stmt
(/*begin_p=*/
1, /*partial_p=*/
0);
371
begin_scope
(sk, NULL);
372
}
373
}
If it is not a template declaration, a node of SCOPE_STMT is
inserted into the statement-list. Argument begin_p
indicates whether this statement opens or
closes a scope; partial_p
is true for a partial scope, i.e, the scope that begins after a label when an
object that needs a cleanup is created. In C++, scopes can be contained wholy
by other scopes, but can’t be overlapped partial each other. So stack is
appropriate for recording scopes, with new node represents new scope.
131
tree
132
add_scope_stmt
(int begin_p, int partial_p)
in c-semantics.c
133
{
134
tree *stack_ptr = current_scope_stmt_stack
();
135
tree ss;
136
tree top = *stack_ptr;
137
138
/*
Build the statement.
*/
139
ss = build_stmt (SCOPE_STMT,
NULL_TREE);
140
SCOPE_BEGIN_P (ss) =
begin_p;
141
SCOPE_PARTIAL_P (ss) =
partial_p;
142
143
/*
Keep the scope stack up to date.
*/
144
if (begin_p)
145
{
146
top = tree_cons (ss,
NULL_TREE, top);
147
*stack_ptr = top;
148
}
149
else
150
{
151
if (partial_p !=
SCOPE_PARTIAL_P (TREE_PURPOSE (top)))
152
abort ();
153
TREE_VALUE (top) = ss;
154
*stack_ptr = TREE_CHAIN
(top);
155
}
156
157
/*
Add the new statement to the statement-tree.
*/
158
add_stmt
(ss);
159
160
return
top;
161
}
The SCOPE_STMT stack mentioned above is returned by current_scope_stmt_stack
.
1199
tree *
1200
current_scope_stmt_stack
(void)
in c-semantics.c
1201
{
1202
return
&cfun
->language->base.x_scope_stmt_stack;
1203
}
At line 151
SCOPE_PARTIAL_P indicates partial scope, which for example:
S s;
l:
S s2;
goto
l;
There is (implicitly) a
new scope after `l', even though there are no curly braces. In particular, when
we hit the goto, we must destroy s2 and then re-construct it.
Then following
nodes will be created before real function-body parsing. We omit the node of last_tree
here, as it always refers to the node at tail of the list.
(Click
here for open
)
Figure 94
:
Before real function-body parsing
Parse
function body
For the keyword “return” seen at line 14368 which follows “)”,
refers to section Build
nodes for method
for detail.
14356
static
tree
14357
cp_parser_function_definition_after_declarator
(cp_parser* parser,
in parser.c
14358
bool inline_p)
14359
{
14360
tree fn;
14361
bool ctor_initializer_p =
false;
14362
bool
saved_in_unbraced_linkage_specification_p;
14363
unsigned
saved_num_template_parameter_lists;
14364
14365
/*
If the next token is `return', then the code may be trying to
14366
make
use of the "named return value" extension that G++ used to
14367
support.
*/
14368
if (cp_lexer_next_token_is_keyword
(parser->lexer, RID_RETURN))
14369
{
14370
/*
Consume the `return' keyword.
*/
14371
cp_lexer_consume_token
(parser->lexer);
14372
/*
Look for the identifier that indicates what value is to be
14373
returned.
*/
14374
cp_parser_identifier
(parser);
14375
/*
Issue an error message.
*/
14376
error ("named return
values are no longer supported");
14377
/*
Skip tokens until we reach the start of the function body.
*/
14378
while
(cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
14379
&&
cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
14380
cp_lexer_consume_token
(parser->lexer);
14381
}
14382
/*
The `extern' in `extern "C" void f () { ... }' does not apply to
14383
anything declared inside `f'.
*/
14384
saved_in_unbraced_linkage_specification_p
14385
=
parser->in_unbraced_linkage_specification_p;
14386
parser->in_unbraced_linkage_specification_p
= false;
14387
/*
Inside the function, surrounding template-parameter-lists do not
14388
apply.
*/
14389
saved_num_template_parameter_lists
14390
=
parser->num_template_parameter_lists;
14391
parser->num_template_parameter_lists
= 0;
14392
/*
If the next token is `try', then we are looking at a
14393
function-try-block.
*/
14394
if (cp_lexer_next_token_is_keyword
(parser->lexer, RID_TRY))
14395
ctor_initializer_p =
cp_parser_function_try_block (parser);
14396
/*
A function-try-block includes the function-body, so we only do
14397
this
next part if we're not processing a function-try-block.
*/
14398
else
14399
ctor_initializer_p
14400
= cp_parser_ctor_initializer_opt_and_function_body
(parser);
14401
14402
/*
Finish the function.
*/
14403
fn = finish_function
((ctor_initializer_p ? 1 : 0) |
14404
(inline_p ?
2 : 0));
14405
/*
Generate code for it, if necessary.
*/
14406
expand_or_defer_fn (fn);
14407
/*
Restore the saved values.
*/
14408
parser->in_unbraced_linkage_specification_p
14409
= saved_in_unbraced_linkage_specification_p;
14410
parser->num_template_parameter_lists
14411
=
saved_num_template_parameter_lists;
14412
14413
return
fn;
14414
}
5.12.3.2.1.2.1.2.1.
Preparation
Though our example method contains an empty function body, but
handling empty function body still embodies rather complex procedure.
11469
static
bool
11470
cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *parser)
in parser.c
11471
{
11472
tree body;
11473
bool ctor_initializer_p;
11474
11475
/*
Begin the function body.
*/
11476
body = begin_function_body
();
11477
/*
Parse the optional ctor-initializer.
*/
11478
ctor_initializer_p =
cp_parser_ctor_initializer_opt (parser);
11479
/*
Parse the function-body.
*/
11480
cp_parser_function_body
(parser);
11481
/*
Finish the function body.
*/
11482
finish_function_body
(body);
11483
11484
return
ctor_initializer_p;
11485
}
The function body is a compound statement itself, which has
following rule:
compound-statement:
{ statement-seq [opt] }
The statement-seq is enclosed the pair of brace which forms a scope
that separates this statement-seq from outside. So before really handling
function body it needs some preparation.
10756
tree
10757
begin_function_body
(void)
in decl.c
10758
{
10759
tree stmt;
10760
10761
if (processing_template_decl
)
10762
/*
Do nothing now.
*/;
10763
else
10764
/*
Always keep the BLOCK node associated with the outermost pair of
10765
curly braces of a function. These are needed for correct
10766
operation of dwarfout.c.
*/
10767
keep_next_level (true);
10768
10769
stmt = begin_compound_stmt
(/*has_no_scope=*/
false);
10770
COMPOUND_STMT_BODY_BLOCK
(stmt) = 1;
10771
10772
if (processing_template_decl
)
10773
/*
Do nothing now.
*/;
10774
else if (DECL_CONSTRUCTOR_P
(current_function_decl
))
10775
begin_constructor_body ();
10776
else if (DECL_DESTRUCTOR_P (current_function_decl
))
10777
begin_destructor_body ();
10778
10779
return
stmt;
10780
}
See that argument has_no_scope
is false for the invocation, which
means the compound statement defines a scope.
998
tree
999
begin_compound_stmt
(bool has_no_scope)
in semantics.c
1000
{
1001
tree r;
1002
int is_try = 0;
1003
1004
r = build_stmt
(COMPOUND_STMT, NULL_TREE);
1005
1006
if (last_tree &&
TREE_CODE (last_tree) == TRY_BLOCK)
1007
is_try = 1;
1008
1009
add_stmt
(r);
1010
if (has_no_scope)
1011
COMPOUND_STMT_NO_SCOPE (r)
= 1;
1012
1013
last_expr_type = NULL_TREE;
1014
1015
if (!has_no_scope)
1016
do_pushlevel
(is_try ? sk_try : sk_block);
1017
else
1018
/* Normally, we try hard to keep the BLOCK for
a
1019
statement-expression. But, if it's a statement-expression with
1020
a
scopeless block, there's nothing to keep, and we don't want
1021
to
accidentally keep a block *inside* the scopeless block.
*/
1022
keep_next_level (false);
1023
1024
return
r;
1025
}
In intermediate tree, brace and parethensis can’t be present. To mark
all statements within the compound statement, a node of COMPOUND_STMT is
created being the head of statement list. At line 84, last_expr_filename
is updated as input_filename
in begin_stmt_tree
.
And if current input file is not the same as that current function belonged,
node of FILE_STMT is created to tell the difference.
81
tree
82
add_stmt
(tree t)
in c-semantics.c
83
{
84
if (input_filename !=
last_expr_filename)
85
{
86
/*
If the filename has changed, also add in a FILE_STMT. Do a string
87
compare first, though, as it might be an
equivalent string.
*/
88
int add = (strcmp
(input_filename, last_expr_filename) != 0);
89
last_expr_filename =
input_filename;
90
if (add)
91
{
92
tree pos = build_nt
(FILE_STMT,
get_identifier
(input_filename));
93
add_stmt (pos);
94
}
95
}
96
97
/*
Add T to the statement-tree.
*/
98
TREE_CHAIN (last_tree) = t;
99
last_tree = t;
100
101
/*
When we expand a statement-tree, we must know whether or not the
102
statements are full-expressions. We record that fact here.
*/
103
STMT_IS_FULL_EXPR_P
(last_tree) = stmts_are_full_exprs_p
();
104
105
return
t;
106
}
Notice that the statement is added at tail of the statement-list,
however, field saved_tree
of the FUNCTION_DECL still refers to the head of the list. Routine stmts_are_full_exprs_p
returns true if the current statement is a full expression (i.e. temporaries
created during that statement should be destroyed at the end of the statement).
Field stmts_are_full_exprs_p
is set as 1 at line 11299 in cxx_push_function_context
.
306
int
307
stmts_are_full_exprs_p
(void)
in semantics.c
308
{
309
return
current_stmt_tree
()->stmts_are_full_exprs_p;
310
}
Then if the compound statement defines a scope, a new scope should
be pushed as sk_block or try_block.
364
void
365
do_pushlevel
(scope_kind sk)
in semantics.c
366
{
367
if (stmts_are_full_exprs_p
())
368
{
369
if (!processing_template_decl
)
370
add_scope_stmt
(/*begin_p=*/
1, /*partial_p=*/
0);
371
begin_scope
(sk, NULL);
372
}
373
}
If it is not a template declaration, a node of SCOPE_STMT is
inserted into the statement-list. Argument begin_p
indicates whether this statement opens or
closes a scope; partial_p
is true for a partial scope, i.e, the scope that begins after a label when an
object that needs a cleanup is created. In C++, scopes can be contained wholy
by other scopes, but can’t be overlapped partial each other. So stack is
appropriate for recording scopes, with new node represents new scope.
131
tree
132
add_scope_stmt
(int begin_p, int partial_p)
in c-semantics.c
133
{
134
tree *stack_ptr = current_scope_stmt_stack
();
135
tree ss;
136
tree top = *stack_ptr;
137
138
/*
Build the statement.
*/
139
ss = build_stmt (SCOPE_STMT,
NULL_TREE);
140
SCOPE_BEGIN_P (ss) =
begin_p;
141
SCOPE_PARTIAL_P (ss) =
partial_p;
142
143
/*
Keep the scope stack up to date.
*/
144
if (begin_p)
145
{
146
top = tree_cons (ss,
NULL_TREE, top);
147
*stack_ptr = top;
148
}
149
else
150
{
151
if (partial_p !=
SCOPE_PARTIAL_P (TREE_PURPOSE (top)))
152
abort ();
153
TREE_VALUE (top) = ss;
154
*stack_ptr = TREE_CHAIN
(top);
155
}
156
157
/*
Add the new statement to the statement-tree.
*/
158
add_stmt
(ss);
159
160
return
top;
161
}
The SCOPE_STMT stack mentioned above is returned by current_scope_stmt_stack
.
1199
tree *
1200
current_scope_stmt_stack
(void)
in c-semantics.c
1201
{
1202
return
&cfun
->language->base.x_scope_stmt_stack;
1203
}
At line 151
SCOPE_PARTIAL_P indicates partial scope, which for example:
S s;
l:
S s2;
goto
l;
There is (implicitly) a
new scope after `l', even though there are no curly braces. In particular, when
we hit the goto, we must destroy s2 and then re-construct it.
Then following
nodes will be created before real function-body parsing. We omit the node of last_tree
here, as it always refers to the node at tail of the list.
(Click
here for open
)
Figure 94
:
Before real function-body parsing
相关文章推荐
- Studying note of GCC-3.4.6 source (79)
- Studying note of GCC-3.4.6 source (97)
- Studying note of GCC-3.4.6 source (106)
- Studying note of GCC-3.4.6 source (112)
- Studying note of GCC-3.4.6 source (116)
- Studying note of GCC-3.4.6 source (126)
- Studying note of GCC-3.4.6 source (138)
- Studying note of GCC-3.4.6 source (141 - cont 1)
- Studying note of GCC-3.4.6 source (148 continue)
- Studying note of GCC-3.4.6 source (155)
- Studying note of GCC-3.4.6 source (26 cont2)
- Studying note of GCC-3.4.6 source (27)
- Studying note of GCC-3.4.6 source (173)
- Studying note of GCC-3.4.6 source (48)
- Studying note of GCC-3.4.6 source (57)
- Studying note of GCC-3.4.6 source (63)
- Studying note of GCC-3.4.6 source (73)
- Studying note of GCC-3.4.6 source (119)
- Studying note of GCC-3.4.6 source (140 - continue)
- Studying note of GCC-3.4.6 source (151)