您的位置:首页 > 其它

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