5.12.5.2.2.2.2.
Return
表达式
返回到
cp_parser_simple_declaration
,在“
SmallObject<> object_;
”中的“
;
”使得该函数返回。然后从
cp_parser_block_declaration
返回到
cp_parser_declaration_statement
,在
6151
行执行
finish_stmt
,但该函数不做任何事,因为
last_expr_type
已经是
NULL
。接着返回至
cp_parser_statement
,在
5504
行的
cp_parser_parse_definitely
毫无疑问地返回了
true
,因而该函数立即返回。那么在
cp_parser_statement_seq_opt
,其
WHILE
循环再一次调用
cp_parser_statement
来处理接下来的“
return
1;
”。在这个函数中关键字“
return
”使得函数
cp_parser_jump_statement
被调用。
6057
static
tree
6058
cp_parser_jump_statement
(cp_parser*
parser)
in parser.c
6059
{
6060
tree statement = error_mark_node;
6061
cp_token *token;
6062
enum
rid
keyword;
6063
6064
/* Peek at the next token.
*/
6065
token = cp_parser_require
(parser, CPP_KEYWORD, "jump-statement");
6066
if (!token)
6067
return
error_mark_node;
6068
6069
/* See what kind of
keyword it is.
*/
6070
keyword = token->keyword;
6071
switch
(keyword)
6072
{
…
6096
case
RID_RETURN:
6097
{
6098
tree expr;
6099
6100
/* If the next token is a `;', then there is
no
6101
expression.
*/
6102
if (cp_lexer_next_token_is_not
(parser->lexer, CPP_SEMICOLON))
6103
expr = cp_parser_expression (parser);
6104
else
6105
expr = NULL_TREE;
6106
/* Build the
return-statement.
*/
6107
statement = finish_return_stmt
(expr);
6108
/* Look for the
final `;'.
*/
6109
cp_parser_require
(parser, CPP_SEMICOLON, "`;'");
6110
}
6111
break
;
…
6134
}
6135
6136
return
statement;
6137
}
在
6103
行,
cp_parser_expression
引导了一个深的函数调用栈,其中从上到下有:
cp_parser_assignment_expression
à
cp_parser_logical_or_expression
à
cp_parser_logical_and_expression
à
cp_parser_inclusive_or_expression
à
cp_parser_exclusive_or_expression
à
cp_parser_and_expression
à
cp_parser_equality_expression
à
cp_parser_relational_expression
à
cp_parser_shift_expression
à
cp_parser_additive_expression
à
cp_parser_multiplicative_expression
à
cp_parser_pm_expression
à
cp_parser_simple_cast_expression
à
cp_parser_cast_expression
à
cp_parser_unary_expression
à
cp_parser_postfix_expression
à
cp_parser_primary_expression
à
cp_lexer_consume_token
à
cp_lexer_read_token
à
cp_lexer_get_preprocessor_token
à
c_lex_with_flags
à
interpret_integer
,
interpret_integer
返回了一个包含值为
1
的
INTEGER_CST
节点的
cpp_token
。结果,在
6103
行的
expr
保存了这个
cpp_token
。
592
tree
593
finish_return_stmt
(tree expr)
in semantics.c
594
{
595
tree r;
596
597
expr = check_return_expr
(expr);
598
if (!processing_template_dec
l)
599
{
600
if (DECL_DESTRUCTOR_P (current_function_decl
))
601
{
602
/* Similarly,
all destructors must run destructors for
603
base-classes
before returning. So, all returns in a
604
destructor
get sent to the DTOR_LABEL; finish_function emits
605
code to
return a value there.
*/
606
return
finish_goto_stmt (dtor_label
);
607
}
608
}
609
r = add_stmt
(build_stmt (RETURN_STMT, expr));
610
finish_stmt
();
611
612
return
r;
613
}
在这里我们需要查看该函数是否会返回一个聚集对象,如果是这样的话,将应用所谓的具名返回值优化(
named return value optimization
)。在下面的还是中,参数
retval
如果不是
NULL
,指向
return
表达式。在下面的
6016
行,
TREE_THIS_VOLATILE
是非
0
值,如果在声明中使用了
volatile
,而如果一个函数被这个谓词所选中,属性“
noreturn
”被应用。根据【
3
】(
15.3.15
)“如果一个
return
语句出现在一个构造函数的
function-try-block
的局部中,该程序非法”。在
6028
行,
in_function_try_handler
如果是非
0
值,表示这样的情形(
function-try-block
的描述参考
为方法构建节点
)。
接着根据【
3
】(
expr.new.13
)“
[
注意:除非一个分配函数被声明为具有一个空的异常规范(
exception-specification
,
(15.4)
),
throw()
,它将通过抛出一个
bad_alloc
异常来显示内存分配的失败(条文
15
,
18.4.2
.1
);否则它返回一个非空指针。如果该分配函数被声明为具有空的异常规范,
throw()
,它返回
null
来显示分配失败,反之一个非空指针
]
。如果该分配函数返回
null
,不应该执行初始化,也不应该调用释放函数,并且该
new
表达式(
new-expression
)的值应该是
null
”。
因此,在
6100
行的条件警告不恰当返回
NULL
的
new
操作符。
6004
tree
6005
check_return_expr
(tree retval)
in typeck.c
6006
{
6007
tree result;
6008
/* The type actually
returned by the function, after any
6009
promotions.
*/
6010
tree valtype;
6011
int fn_returns_value_p;
6012
6013
/* A `volatile'
function is one that isn't supposed to return, ever.
6014
(This is a G++ extension, used
to get better code for functions
6015
that call the `volatile'
function.)
*/
6016
if (TREE_THIS_VOLATILE (current_function_decl
))
6017
warning ("function declared `noreturn'
has a `return' statement");
6018
6019
/* Check for
various simple errors.
*/
6020
if (DECL_DESTRUCTOR_P (current_function_decl
))
6021
{
6022
if (retval)
6023
error ("returning a value from a
destructor");
6024
return
NULL_TREE;
6025
}
6026
else if (DECL_CONSTRUCTOR_P (current_function_decl
))
6027
{
6028
if (in_function_try_handler
)
6029
/* If a return
statement appears in a handler of the
6030
function-try-block of a
constructor, the program is ill-formed.
*/
6031
error ("cannot return from a handler
of a function-try-block of a constructor");
6032
else if (retval)
6033
/* You can't
return a value from a constructor.
*/
6034
error ("returning a value from a
constructor");
6035
return
NULL_TREE;
6036
}
6037
6038
if (processing_template_decl
)
6039
{
6040
current_function_returns_value
= 1;
6041
return
retval;
6042
}
6043
6044
/* When no explicit
return-value is given in a function with a named
6045
return value, the named return
value is used.
*/
6046
result = DECL_RESULT (current_function_decl
);
6047
valtype = TREE_TYPE (result);
6048
my_friendly_assert (valtype != NULL_TREE,
19990924);
6049
fn_returns_value_p = !VOID_TYPE_P (valtype);
6050
if (!retval && DECL_NAME (result)
&& fn_returns_value_p)
6051
retval = result;
6052
6053
/* Check for a
return statement with no return value in a function
6054
that's supposed to return a
value.
*/
6055
if (!retval && fn_returns_value_p)
6056
{
6057
pedwarn ("return-statement with no
value, in function returning '%T'",
6058
valtype);
6059
/* Clear this, so
finish_function won't say that we reach the
6060
end of a non-void function
(which we don't, we gave a
6061
return!).
*/
6062
current_function_returns_null
= 0;
6063
}
6064
/* Check for a return
statement with a value in a function that
6065
isn't supposed to return a
value.
*/
6066
else if (retval &&
!fn_returns_value_p)
6067
{
6068
if (VOID_TYPE_P (TREE_TYPE (retval)))
6069
/* You can
return a `void' value from a function of `void'
6070
type. In that case, we
have to evaluate the expression for
6071
its side-effects.
*/
6072
finish_expr_stmt (retval);
6073
else
6074
pedwarn ("return-statement with a
value, in function "
6075
"returning 'void'");
6076
6077
current_function_returns_null
= 1;
6078
6079
/* There's really
no value to return, after all.
*/
6080
return
NULL_TREE;
6081
}
6082
else if (!retval)
6083
/* Remember that
this function can sometimes return without a
6084
value.
*/
6085
current_function_returns_null
= 1;
6086
else
6087
/* Remember that this function did return a
value.
*/
6088
current_function_returns_value
= 1;
6089
6090
/* Check for
erroneous operands -- but after giving ourselves a
6091
chance to provide an error
about returning a value from a void
6092
function.
*/
6093
if (error_operand_p (retval))
6094
{
6095
current_function_return_value
= error_mark_node;
6096
return
error_mark_node;
6097
}
6098
6099
/* Only operator
new(...) throw(), can return NULL [expr.new/13].
*/
6100
if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl
)
== NEW_EXPR
6101
||
DECL_OVERLOADED_OPERATOR_P (current_function_decl
) == VEC_NEW_EXPR)
6102
&& !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl
))
6103
&& ! flag_check_new
6104
&& null_ptr_cst_p (retval))
6105
warning ("`operator new' must not
return NULL unless it is declared `throw()' (or -fcheck-new is in
effect)");
6106
6107
/* Effective C++
rule 15. See also start_function.
*/
6108
if (warn_ecpp
6109
&& DECL_NAME (current_function_decl
)
== ansi_assopname(NOP_EXPR)
6110
&& retval != current_class_ref
)
6111
warning ("`operator=' should return a
reference to `*this'");
6112
6113
/* The fabled Named
Return Value optimization, as per [class.copy]/15:
6114
6115
[...] For a function with a
class return type, if the expression
6116
i
n the return statement is the name of a local
object, and the cv-
6117
unqualified type of the local
object is the same as the function
6118
return type, an implementation
is permitted to omit creating the tem-
6119
porary object to hold the
function return value [...]
6120
6121
So, if this is a value-returning
function that always returns the same
6122
local variable, remember it.
6123
6124
It might be nice to be more
flexible, and choose the first suitable
6125
variable even if the function
sometimes returns something else, but
6126
then we run the risk of
clobbering the variable we chose if the other
6127
returned expression uses the
chosen variable somehow. And people expect
6128
this restriction, anyway.
(jason 2000-11-19)
6129
6130
See finish_function,
cxx_expand_function_start, and
6131
cp_copy_res_decl_for_inlining
for other pieces of this
6132
optimization.
*/
6133
6134
if (fn_returns_value_p && flag_elide_constructors
)
6135
{
6136
if (retval != NULL_TREE
6137
&& (current_function_return_value
==
NULL_TREE
6138
|| current_function_return_value
==
retval)
6139
&& TREE_CODE (retval) ==
VAR_DECL
6140
&& DECL_CONTEXT (retval) == current_function_decl
6141
&& ! TREE_STATIC (retval)
6142
&& (DECL_ALIGN (retval)
6143
>= DECL_ALIGN (DECL_RESULT (current_function_decl
)))
6144
&& same_type_p
((TYPE_MAIN_VARIANT
6145
(TREE_TYPE (retval))),
6146
(TYPE_MAIN_VARIANT
6147
(TREE_TYPE (TREE_TYPE
(current_function_decl
))))))
6148
current_function_return_value
= retval;
6149
else
6150
current_function_return_value
= error_mark_node;
6151
}
6152
6153
/* We don't need to
do any conversions when there's nothing being
6154
returned.
*/
6155
if (!retval)
6156
return
NULL_TREE;
6157
6158
/* Do any required
conversions.
*/
6159
if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl
))
6160
/* No conversions
are required.
*/
6161
;
6162
else
6163
{
6164
/* The type the
function is declared to return.
*/
6165
tree functype = TREE_TYPE (TREE_TYPE (current_function_decl
));
6166
6167
/* First convert
the value to the function's return type, then
6168
to the type of return
value's location to handle the