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