现在的位置: 首页 > 综合 > 正文

GCC-3.4.6源代码学习笔记(144)

2013年07月12日 ⁄ 综合 ⁄ 共 9862字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.