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

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

2013年07月04日 ⁄ 综合 ⁄ 共 10083字 ⁄ 字号 评论关闭

5.12.5.2.2.2.1.4.   



完成具现

现在继续我们模板具现例子的处理,在
前端部分的初始化



一节,我们已经看到当使用命令行选项
-frepo

时,
init_repo


会产生一个
.rpo
文件,或读入一个已经存在的
.rpo
文件。下面的
repo_template_used


将在对应的
.rpo
文件中记录该模板具现的使用,这个信息将被编译器及
collect2

GCC
自带的链接器)在以后使用。

 

instantiate_class_template (continue)

 

5473  


 
/* Clear this now
so repo_template_used is happy. 
*/

5474  


 
TYPE_BEING_DEFINED (type) = 0;

5475  


 
repo_template_used (type);

5476  

5477  


 
/* Now that the
class is complete, instantiate default arguments for

5478  


   
any member functions. We don't
do this earlier because the

5479  


   
default arguments may
reference members of the class. 
*/

5480  


 
if (!PRIMARY_TEMPLATE_P (template))

5481  


   
for
(t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))

5482  


     
if (TREE_CODE (t) == FUNCTION_DECL

5483  


        
/*
Implicitly generated member functions will not have template

5484  


          
information; they are
not instantiations, but instead are

5485  


          
created
"fresh" for each instantiation. 


*/

5486  


        

&& DECL_TEMPLATE_INFO (t))

5487  


       

tsubst_default_arguments (t);

5488  

5489  


 
popclass
();

5490  


 
pop_from_top_level
();

5491  


 
pop_deferring_access_checks
();

5492  


 
pop_tinst_level ();

5493  

5494  


 
if (TYPE_CONTAINS_VPTR_P (type))

5495  


   
keyed_classes = tree_cons (NULL_TREE, type,
keyed_classes);

5496  

5497  


 
return
type;

5498  


}

 

然后记得通过
popclass


退出类的作用域;接着通过
pop_from_top_level


恢复原有的作用域。还有递减
tinst_depth

并通过
pop_tinst_level


更新
current_tinst_level

,它是
EXPR_WITH_FILE_LOCATION
类型的节点。因为类
C
包含
vtable
,它被视为锁定类(
keyed class
)。


instantiate_class_template


退出,我们回到
complete_type


,然后
layout_var_decl


。这个模板是在函数
main


中具现,因此
current_function_decl

指向该函数的作用域,那么在
layout_var_decl



4100
行,
push_local_name


把这个变量加入函数的作用域。

 

948   


static
void

949   


push_local_name

(tree decl)                                                                           

in decl.c

950   


{

951   


 
size_t i, nelts;

952   


 
tree t, name;

953   

954   


 
timevar_push (TV_NAME_LOOKUP);

955   


 
if (!local_names)

956   


   
VARRAY_TREE_INIT (local_names, 8,
"local_names");

957   

958   


 
name = DECL_NAME (decl);

959   

960   


 
nelts = VARRAY_ACTIVE_SIZE (local_names);

961   


 
for
(i = 0; i < nelts; i++)

962   


 
{

963   


   
t = VARRAY_TREE (local_names, i);

964   


   
if (DECL_NAME (t) == name)

965   


   
{

966   


   
  
if
(!DECL_LANG_SPECIFIC (decl))

967   


   
    
retrofit_lang_decl (decl);

968   


   
  
DECL_LANG_SPECIFIC
(decl)->decl_flags.u2sel = 1;

969   


   
  
if
(DECL_LANG_SPECIFIC (t))

970   


   
 
   
DECL_DISCRIMINATOR (decl) =
DECL_DISCRIMINATOR (t) + 1;

971   


   
  
else

972   


   
    
DECL_DISCRIMINATOR (decl) = 1;

973   

974   


   
  
VARRAY_TREE (local_names, i) = decl;

975   


   
  
timevar_pop (TV_NAME_LOOKUP);

976   


   
  
return
;

977   


   
}

978   


 
}

979   

980   


 
VARRAY_PUSH_TREE (local_names, decl);

981   


 
timevar_pop (TV_NAME_LOOKUP);

982   


}

 

上面的
local_names

是一个访问
cfun


language

部分
x_local_names

域的宏,这个域是一个可变的数组,保存了在由
cfun

所表示的函数中声明的布局名字。

5.12.5.2.2.2.1.5.   



完成

VAR_DECL

现在我们回到了
cp_finish_decl


,曙光就在前面!

 

cp_finish_decl (continue)

 

4962  


 
/* Output the
assembler code and/or RTL code for variables and functions,

4963  


   
unless the type is an
undefined structure or union.

4964  


   
If not, it will get done when
the type is completed. 
*/

4965  


 
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE
(decl) == FUNCTION_DECL)

4966  


 
{

4967  


   
if (TREE_CODE (decl) == VAR_DECL)

4968  


     
maybe_commonize_var (decl);

4969  

4970  


   
make_rtl_for_nonlocal_decl (decl, init,
asmspec);

4971  

4972  


   
if (TREE_CODE (type) == FUNCTION_TYPE

4973  


      
|| TREE_CODE (type) == METHOD_TYPE)

4974  


    
abstract_virtuals_error
(decl,

4975  


                       
strip_array_types
(TREE_TYPE (type)));

4976  


   
else if (POINTER_TYPE_P (type) || TREE_CODE
(type) == ARRAY_TYPE)

4977  


   
{

           

4986  


   
}

4987  


   
else

4988  


     
abstract_virtuals_error
(decl, type);

4989  

4990  


   
if (TREE_CODE (decl) == FUNCTION_DECL

4991  


      
|| TREE_TYPE (decl) == error_mark_node)

4992  


     
/* No
initialization required. 
*/

4993  


     
;

4994  


   
else if (DECL_EXTERNAL (decl)

4995  


         
&& ! (DECL_LANG_SPECIFIC
(decl)

4996  


              
&&
DECL_NOT_REALLY_EXTERN (decl)))

4997  


   
{

4998  


     
if (init)

4999  


       
DECL_INITIAL (decl) = init;

5000  


   
}

5001  


   
else

5002  


   
{

5003  


     
/* A variable
definition. 
*/

5004  


 
    
if
(DECL_FUNCTION_SCOPE_P (decl))

5005  


     
{

5006  


       
/* This is a
local declaration. 
*/

5007  


       
maybe_inject_for_scope_var (decl);

5008  


       
/* Initialize
the local variable. 
*/

5009  


       
if (processing_template_decl)

5010  


       
{

5011  


         
if (init || DECL_INITIAL (decl) ==
error_mark_node)

5012  


           
DECL_INITIAL (decl) = init;

5013  


       
}

5014  


       
else if (!TREE_STATIC (decl))

5015  


         
initialize_local_var
(decl, init);

5016  


     
}

5017  

5018  


     
/* If a
variable is defined, and then a subsequent

5019  


       
definintion with external
linkage is encountered, we will

5020  


       
get here twice for the
same variable. We want to avoid

5021  


       
calling expand_static_init
more than once. For variables

5022  


       
that are not static data
members, we can call

5023  


       
expand_static_init only
when we actually process the

5024  


       
initializer. It is not
legal to redeclare a static data

5025  


       
member, so this issue does
not arise in that case. 
*/

5026  


     
if (var_definition_p &&
TREE_STATIC (decl))

5027  


       
expand_static_init (decl, init);

5028  


   
}

5029  


finish_end0:

5030  

5031  


   
/* Undo call to
`pushclass' that was done in `start_decl'

5032  


    
 
due to initialization of qualified member
variable.

5033  


    
 
i.e., Foo::x = 10; 
*/

5034  


   
{

5035  


     
tree context = CP_DECL_CONTEXT (decl);

5036  


     
if (context

5037  


        
&& TYPE_P (context)

5038  


        
&& (TREE_CODE (decl) ==
VAR_DECL

5039  


            
/* We
also have a pushclass done that we need to undo here

5040  


       
  
    
 
if we're at top level and declare a
method. 
*/

5041  


            
|| TREE_CODE (decl) ==
FUNCTION_DECL)

5042  


        
/* If size
hasn't been set, we're still defining it,

5043  


    
      
and therefore inside the class body;
don't pop

5044  


      
    
the binding level.. 
*/

5045  


        
&& COMPLETE_TYPE_P (context)

5046  


        
&& context == current_class_type

)

5047  


       
pop_nested_class ();

5048  


   
}

5049  


 
}

5050  

5051  


 
/* If a
CLEANUP_STMT was created to destroy a temporary bound to a

5052  


   
reference, insert it in the
statement-tree now. 
*/

5053  


 
if (cleanup)

5054  


   
add_stmt (cleanup);

5055  

5056  


finish_end:

5057  

5058  


 
if (was_readonly)

5059  


   
TREE_READONLY (decl) = 1;

5060  

5061  


 
/* If this was
marked 'used', be sure it will be output. 

*/

5062  


 
if (lookup_attribute ("used",
DECL_ATTRIBUTES (decl)))

5063  


   
mark_referenced (DECL_ASSEMBLER_NAME
(decl));

5064  


}

 

在函数剩余的代码里,为了把模板的具现
obj_
按照局部变量来处理,在
5015
行调用了
initialize_local_var


 

698   


static
void

4699  


initialize_local_var

(tree decl, tree
init)                                                             

in decl.c

4700  


{

4701  


 
tree type = TREE_TYPE (decl);

4702  


 
tree cleanup;

4703  

4704  


 
my_friendly_assert (TREE_CODE (decl) ==
VAR_DECL

4705  


   
               
|| TREE_CODE (decl) ==
RESULT_DECL,

4706  


                  
20021010);

4707  


 
my_friendly_assert (!TREE_STATIC (decl),
20021010);

4708  

4709  


 
if (DECL_SIZE (decl) == NULL_TREE)

4710  


 
{

4711  


   
/* If we used it
already as memory, it must stay in memory. 

*/

4712  


   
DECL_INITIAL (decl) = NULL_TREE;

4713  


   
TREE_ADDRESSABLE (decl) = TREE_USED (decl);

4714  


 
}

4715  

4716  


 
if (DECL_SIZE (decl) && type !=
error_mark_node)

4717  


 
{

4718  


   
int already_used;

4719  

4720  


  
 
/* Compute and store the initial value. 
*/

4721  


   
already_used = TREE_USED (decl) ||
TREE_USED (type);

4722  

4723  


   
/* Perform the
initialization. 
*/

4724  


   
if (init)

4725  


   
{

4726  


     
int saved_stmts_are_full_exprs_p;

4727  

4728  


     
my_friendly_assert (building_stmt_tree
(), 20000906);

4729  


     
saved_stmts_are_full_exprs_p =
stmts_are_full_exprs_p ();

4730  


     
current_stmt_tree
()->stmts_are_full_exprs_p = 1;

4731  


     
finish_expr_stmt (init);

4732  


     
current_stmt_tree
()->stmts_are_full_exprs_p =

4733  


        
saved_stmts_are_full_exprs_p;

4734  


    
 
}

4735  

4736  


   
/* Set this to 0
so we can tell whether an aggregate which was

4737  


     
initialized was ever used.
Don't do this if it has a

4738  


     
destructor, so we don't
complain about the 'resource

4739  


     
allocation is
initialization' idiom. Now set

4740  


     
attribute((unused)) on types
so decls of that type will be

4741  


     
marked used. (see TREE_USED,
above.) 
*/

4742  


   
if (TYPE_NEEDS_CONSTRUCTING (type)

4743  


      
&& ! already_used

4744  


      
&& TYPE_HAS_TRIVIAL_DESTRUCTOR
(type)

4745  


      
&& DECL_NAME (decl))

4746  


     
TREE_USED (decl) = 0;

4747  


   
else if (already_used)

4748  


     
TREE_USED (decl) = 1;

4749  


 
}

4750  

4751  


 
/* Generate a
cleanup, if necessary. 
*/

4752  


 
cleanup = cxx_maybe_build_cleanup
(decl);

4753  


 
if (DECL_SIZE (decl) && cleanup)

4754  


   
finish_decl_cleanup
(decl, cleanup);

4755  


}

 

这里参数
init

来自声明符中跟在“
=
”后面的部分,它是由程序员指定的初始值,而不是在前面我们看到的由编译器指定的。显然,对于我们的例子,
init


NULL

接着看
4752
行的
cxx_maybe_build_cleanup


。编译器可能会插入代码来清除局部变量,在它退出其作用域时。

 

11215


tree

11216


cxx_maybe_build_cleanup

(tree decl)                                                              

in decl.c

11217


{

11218


 
tree type = TREE_TYPE (decl);

11219

11220


 
if (type != error_mark_node &&
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))

11221


 
{

11222


   
int flags =
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;

11223


   
tree rval;

11224

11225


   
if (TREE_CODE (type) == ARRAY_TYPE)

11226


     
rval = decl;

11227


   
else

11228


   
{

11229


     
cxx_mark_addressable (decl);

11230


     
rval = build_unary_op (ADDR_EXPR, decl,
0);

11231


   
}

11232

11233


   
/* Optimize for
space over speed here. 
*/

11234


   
if (! TYPE_USES_VIRTUAL_BASECLASSES (type)

11235


   
    
|| flag_expensive_optimizations

)

11236


     
flags |= LOOKUP_NONVIRTUAL;

11237

11238


   
rval = build_delete
(TREE_TYPE (rval), rval,

11239


                   
sfk_complete_destructor,
flags, 0);

11240

11241


   
if (TYPE_USES_VIRTUAL_BASECLASSES (type)

11242


       
&& ! TYPE_HAS_DESTRUCTOR
(type))

11243


     
rval = build_compound_expr (rval, build_vbase_delete
(type, decl));

11244

11245


   
return
rval;

11246


 
}

11247


 
return
NULL_TREE;

11248


}

 

断言
TYPE_HAS_NONTRIVIAL_DESTRUCTOR

true
,如果该类型的析构函数不是平凡的(对于某个类,如果我们没有定义析构函数,并且对于所有的基类及非静态数据成员,
TYPE_HAS_NONTRIVIAL_DESTRUCTOR

false
,那么对于这个类,
TYPE_HAS_NONTRIVIAL_DESTRUCTOR

返回
false
)。

这就是为什么如果析构函数不做任何事就不要定义它。虽然编译器会为你添加一个隐含的析构函数,但只要它的基类及非静态数据成员都具有平凡析构函数,它就会被标记为平凡。结果,在这里不会产生用于清除的代码。

如果期望清除操作,首先从局部变量
decl

构建出一个
ADDR_EXPR
,因为
delete

操作符总是作用于指针。在程序员使用
register

强制把变量放入寄存器的情形下,
cxx_mark_addressable


将修改所产生的代码以表示把这个局部变量放入栈中。

 

2866  


tree

2867  


build_delete

(tree type, tree addr,
special_function_kind auto_delete,                   

in init.c

2868  


          
int flags, int use_global_delete)

2869  


{

2870  


 
tree expr;

2871  

2872  


 
if (addr == error_mark_node)

2873  


   
return
error_mark_node;

2874  

2875  


 
/* Can happen when
CURRENT_EXCEPTION_OBJECT gets its type

2876  


   
set to `error_mark_node'
before it gets properly cleaned up. 
*/

2877  


 
if (type == error_mark_node)

2878  


   
return
error_mark_node;

2879  

2880  

【上篇】
【下篇】

抱歉!评论已关闭.