Studying note of GCC-3.4.6 source (64)

4.3.1.7.8.            Finish initialization

Below abort_fndecl represents function abort, and function build_library_fn_ptr like build_library_fn, but takes a C string instead of an IDENTIFIER_NODE.

 

cxx_init_decl_processing (continue)

 

3115     abort_fndecl

3116       = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);

3117

3118     /* Perform other language dependent initializations.  */

3119     init_class_processing ();

3120     init_search_processing ();

3121     init_rtti_processing ();

3122  

3123     if (flag_exceptions)

3124       init_exception_processing ();

3125  

3126     if (! supports_one_only ())

3127       flag_weak = 0;

3128  

3129     make_fname_decl = cp_make_fname_decl;

3130     start_fname_decls ();

3131  

3132     /* Show we use EH for cleanups.  */

3133     using_eh_for_cleanups ();

3134  

3135     /* Maintain consistency. Perhaps we should just complain if they

3136     say -fwritable-strings?  */

3137     if (flag_writable_strings)

3138       flag_const_strings = 0;

3139   }

4.3.1.7.8.1.      Initialize class processing

During handling class declaration, GCC uses following global variables to control the process. Among them, current_class_depth indicates the level of the nesting, and the classes nesting form a stack current_class_stack, which uses current_class_stack_size to tell the size. GNU C++ has an extension, allows class being defined within function body, which can only be visible there. To discriminate the class from others, the class is saved by local_classes.

 

5424   void

5425   init_class_processing (void)                                                                      in class.c

5426   {

5427     current_class_depth = 0;

5428     current_class_stack_size = 10;

5429     current_class_stack

5430       = xmalloc (current_class_stack_size * sizeof (struct class_stack_node));

5431     VARRAY_TREE_INIT (local_classes, 8, "local_classes");

5432  

5433     ridpointers[(int) RID_PUBLIC] = access_public_node;

5434     ridpointers[(int) RID_PRIVATE] = access_private_node;

5435     ridpointers[(int) RID_PROTECTED] = access_protected_node;

5436   }

 

And search_obstack initialized below is useless in current version, and has been removed in V4.

 

2346   void

2347   init_search_processing (void)                                                                   in search.c

2348   {

2349     gcc_obstack_init (&search_obstack);

2350   }

4.3.1.7.8.2.      Runtime type identification (RTTI)

4.3.1.7.8.2.1.              Create TYPE_DECL

To support RTTI (runtime type identification) which allows programs that manipulate objects as pointers or references to base classes to retrieve the actual derived types of the objects to which these pointers or references refer, GCC offers two operators: dynamic_cast and typeid. The returned type of typeid is type_info, and the definition of type_info is implement dependent. Here in the initialization of RTTI, unlike std::bad_alloc, full definition will be created as this type is expected by runtime environment.

 

115     void

116     init_rtti_processing (void)                                                                               in rtti.c

117     {

118       tree const_type_info_type;

119    

120      push_namespace (std_identifier);

121      type_info_type_node

122        = xref_tag (class_type, get_identifier ("type_info"),

123                 true, false);

124      pop_namespace ();

125      const_type_info_type = build_qualified_type (type_info_type_node,

126                                            TYPE_QUAL_CONST);

127      type_info_ptr_type = build_pointer_type (const_type_info_type);

128      type_info_ref_type = build_reference_type (const_type_info_type);

129   

130      VARRAY_TREE_INIT (unemitted_tinfo_decls, 10, "RTTI decls");

131   

132      create_tinfo_types ();

133    }

 

Now xref_tag tries to get the struct, enum or union (tag_code says which) with name. Defines the tag as a forward-reference if it is not defined.

If argument globalize is false, it means the identifier name is a definition. In C++, it first allows to define types of same name in different binding scope; second, in the same binding scope, different types of same name is an error unless the definitions are identical. At line 9476, lookup_tag tries to find out the type definition specified by code and name within binding scope referred by b. We will see the detail of the function later.

While if globalize is true, the tag is just type declaration. In C++, we can use the reference of an undefined user defining types restrictly by just declare it. For example,

class A;

A* pa = NULL;

Within GCC, when it finds that nothing can be found, it will create a fake type (remember std::bad_alloc), then declares implicit typedef for it and pushes TYPE_DECL created by implicit typedef within specified binding scope. Thus the forward declaration in fact refers to this TYPE_DECL, then later when the real definition encountered, the corresponding type node (of RECORD_TYPE/UNION_TYPE/ ENUMERAL_TYPE) is updated accordingly. And while GCC finds existing type declaration (no fake type), special handling is needed when the declaration relates to generic programing, we will see it shortly.

 

9443   tree

9444   xref_tag (enum tag_types tag_code, tree name,                                                         in decl.c

9445          bool globalize, bool template_header_p)

9446   {

9447     enum tree_code code;

9448     tree t;

9449     struct cp_binding_level *b = current_binding_level;

9450     tree context = NULL_TREE;

9451  

9452     timevar_push (TV_NAME_LOOKUP);

9453  

9454     my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);

9455  

9456     switch (tag_code)

9457     {

9458       case record_type:

9459       case class_type:

9460         code = RECORD_TYPE;

9461         break;

9462       case union_type:

9463         code = UNION_TYPE;

9464         break;

9465       case enum_type:

9466         code = ENUMERAL_TYPE;

9467         break;

9468       default:

9469         abort ();

9470     }

9471  

9472     if (! globalize)

9473     {

9474       /* If we know we are defining this tag, only look it up in

9475         this scope and don't try to find it as a type.  */

9476       t = lookup_tag (code, name, b, 1);

9477     }

9478     else

9479     {

9480       tree decl = lookup_name (name, 2);

 

Here globalize is true, it uses lookup_name to find out the type declaration as the second argument indicates to reject non-type declarations. lookup_name is a complex function, we skip it here temporary to not to make the procedure too long. For out case here, lookup_name should returns NULL as it must be the first to declare this type.

 

xref_tag (continue)

 

9558     if (! t)

9559     {

9560       /* If no such tag is yet defined, create a forward-reference node

9561         and record it as the "definition".

9562         When a real declaration of this type is found,

9563         the forward-reference will be altered into a real type.  */

9564       if (code == ENUMERAL_TYPE)

9565       {

9566         error ("use of enum `%#D' without previous declaration", name);

9567         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

9568       }

9569       else

9570       {

9571         t = make_aggr_type (code);

9572         TYPE_CONTEXT (t) = context;

9573         pushtag (name, t, globalize);

9574       }

9575     }

9576    else

9577     {

          ...

9587     }

9588  

9589     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);

9590   }

 

As the tag should not be found by lookup_name at line 9480, a node will be created for it. And as argument tag_code is class_type, the node should be RECORD_TYPE, and its context is first set as empty (see NULL_TREE at line 9450).

 

4589   void

4590   pushtag (tree name, tree type, int globalize)                                        in name-lookup.c

4591   {

4592     struct cp_binding_level *b;

4593  

4594     timevar_push (TV_NAME_LOOKUP);

4595     b = current_binding_level;

4596     while (/* Cleanup scopes are not scopes from the point of view of

4597             the language.  */

4598       b->kind == sk_cleanup

4599       /* Neither are the scopes used to hold template parameters

4600         for an explicit specialization. For an ordinary template

4601         declaration, these scopes are not scopes from the point of

4602         view of the language -- but we need a place to stash

4603         things that will go in the containing namespace when the

4604         template is instantiated.  */

4605       || (b->kind == sk_template_parms && b->explicit_spec_p)

4606       || (b->kind == sk_class

4607         && (globalize

4608           /* We may be defining a new type in the initializer

4609             of a static member variable. We allow this when

4610             not pedantic, and it is particularly useful for

4611             type punning via an anonymous union.  */

4612           || COMPLETE_TYPE_P (b->this_entity))))

4613       b = b->level_chain;

4614  

4615     if (b->type_decls == NULL)

4616       b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);

4617     binding_table_insert (b->type_decls, name, type);

 

pushtag first pushes type definition into current namespace. As we have seen, user defined type definition within a binding scope, is kept at field type_decls of the corresponding cp_binding_level. Below binding_table_insert handles the detail.

 

190    static void

191    binding_table_insert (binding_table table, tree name, tree type)             in name-lookup.c

192    {

193      const unsigned int hash = IDENTIFIER_HASH_VALUE (name);

194      const size_t i = ENTRY_INDEX (hash, table->chain_count);

195      binding_entry entry = binding_entry_make (name, type);

196   

197      entry->chain = table->chain[i];

198      table->chain[i] = entry;

199      ++table->entry_count;

200   

201      if (3 * table->chain_count < 5 * table->entry_count)

202        binding_table_expand (table);

203    }

 

Notice that type_decls in fact is a hashtable, all type definitions have the same hash value will be linked tegother. To control the length of the list, if the number of lists (field chain_count) has following relation with number of entries (field entry_count): 3*table->chain_count < 5*table->entry_count, binding_table_expand will expand the number of lists by double and rehash and relink types recorded.

 

67      static inline binding_entry

68      binding_entry_make (tree name, tree type)                                                 in name-lookup.c

69      {

70        binding_entry entry;

71     

72        if (free_binding_entry)

73        {

74          entry = free_binding_entry;

75          free_binding_entry = entry->chain;

76        }

77        else

78          entry = ggc_alloc (sizeof (struct binding_entry_s));

79     

80        entry->name = name;

81        entry->type = type;

82        entry->chain = NULL;

83     

84        return entry;

85      }

 

In above binding_entry_make, though the identifier is associated with the type definition within an instance of binding_entry, however the node of identifier has not bound with TYPE_DECL, so in below IDENTIFIER_TYPE_VALUE returns NULL.

 

1700   tree

1701   identifier_type_value (tree id)                                                           in name-lookup.c

1702   {

1703     timevar_push (TV_NAME_LOOKUP);

1704     /* There is no type with that name, anywhere.  */

1705     if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)

1706       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);

1707     /* This is not the type marker, but the real thing.  */

1708     if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)

1709       POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));

1710    /* Have to search for it. It must be on the global level, now.

1711       Ask lookup_name not to return non-types.  */

1712     id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);

1713     if (id)

1714       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));

1715     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);

1716   }

 

IDENTIFIER_TYPE_VALUE is just another name of identifier_type_value. Here in our case, REAL_IDENTIFIER_TYPE_VALUE should return NULL_TREE while type at line 4622 below is the RECORD_TYPE node just generated.

 

pushtag (continue)

 

4619     if (name)

4620     {

4621       /* Do C++ gratuitous typedefing.  */

4622      if (IDENTIFIER_TYPE_VALUE (name) != type)

4623       {

4624         tree d = NULL_TREE;

4625         int in_class = 0;

4626         tree context = TYPE_CONTEXT (type);

4627  

4628         if (! context)

4629         {

4630           tree cs = current_scope ();

4631  

4632           if (! globalize)

4633            context = cs;

4634           else if (cs != NULL_TREE && TYPE_P (cs))

4635             /* When declaring a friend class of a local class, we want

4636               to inject the newly named class into the scope

4637               containing the local class, not the namespace scope.  */

4638             context = decl_function_context (get_type_decl (cs));

4639         }

4640         if (!context)

4641           context = current_namespace;

4642  

4643         if (b->kind == sk_class

4644            || (b->kind == sk_template_parms

4645              && b->level_chain->kind == sk_class))

4646           in_class = 1;

4647  

4648         if (current_lang_name == lang_name_java)

4649           TYPE_FOR_JAVA (type) = 1;

4650  

4651         d = create_implicit_typedef (name, type);

4652         DECL_CONTEXT (d) = FROB_CONTEXT (context);

4653         if (! in_class)

4654           set_identifier_type_value_with_scope (name, d, b);

 

Remember that the type context is NULL, so at line 4630, current_scope is invoked. It is a macro selects between current_function_decl and current_class_type accordingly, which always returns NULL for namespace scope. Then as we are within std namespace, it sets the context with current namespace scope at line 4641.

Next at line 4651, a TYPE_DECL node is created for the type by create_implicit_typedef. Then in set_identifier_type_value_with_scope, this TYPE_DECL node (not type definition) will be recorded into field namespace_bindings of the node of identifier.

 

1731   static void

1732   set_identifier_type_value_with_scope (tree id, tree decl, cxx_scope *b)        in name-lookup.c

1733   {

1734     tree type;

1735  

1736     if (b->kind != sk_namespace)

1737     {

1738       /* Shadow the marker, not the real thing, so that the marker

1739         gets restored later.  */

1740       tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);

1741       b->type_shadowed

1742          = tree_cons (id, old_type_value, b->type_shadowed);

1743       type = decl ? TREE_TYPE (decl) : NULL_TREE;

1744     }

1745     else

1746     {

1747       cxx_binding *binding =

1748           binding_for_name (NAMESPACE_LEVEL (current_namespace), id);

1749       if (decl)

1750       {

1751         if (binding->value)

1752           supplement_binding (binding, decl);

1753         else

1754           binding->value = decl;

1755       }

1756       else

1757         abort ();

1758       /* Store marker instead of real type.  */

1759       type = global_type_node;

1760     }

1761     SET_IDENTIFIER_TYPE_VALUE (id, type);

1762   }

 

Above the assignment operation at line 1754, sets the declaration (it’s a type declaratoin) for the identifier currently matching. From then no, in current scope, the identifier stands for this type.

 

pushtag (continue)

 

4656         d = maybe_process_template_type_declaration (type,

4657                                                globalize, b);

4658  

4659         if (b->kind == sk_class)

4660         {

4661           if (!PROCESSING_REAL_TEMPLATE_DECL_P ())

4662             /* Put this TYPE_DECL on the TYPE_FIELDS list for the

4663               class. But if it's a member template class, we

4664               want the TEMPLATE_DECL, not the TYPE_DECL, so this

4665               is done later.  */

4666             finish_member_declaration (d);

4667           else

4668             pushdecl_class_level (d);

4669         }

4670         else

4671           d = pushdecl_with_scope (d, b);

4672  

4673         /* FIXME what if it gets a name from typedef?  */

4674         if (ANON_AGGRNAME_P (name))

4675           DECL_IGNORED_P (d) = 1;

4676  

4677         TYPE_CONTEXT (type) = DECL_CONTEXT (d);

4678  

4679         /* If this is a local class, keep track of it. We need this

4680           information for name-mangling, and so that it is possible to find

4681           all function definitions in a translation unit in a convenient

4682           way. (It's otherwise tricky to find a member function definition

4683           it's only pointed to from within a local class.)  */

4684         if (TYPE_CONTEXT (type)

4685            && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL

4686            && !processing_template_decl)

4687           VARRAY_PUSH_TREE (local_classes, type);

4688       }

4689       if (b->kind == sk_class

4690           && !COMPLETE_TYPE_P (current_class_type))

4691       {

4692         maybe_add_class_template_decl_list (current_class_type,

4693                                        type, /*friend_p=*/0);

4694         CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;

4695       }

4696     }

4697  

4698     if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)

4699       /* Use the canonical TYPE_DECL for this node.  */

4700       TYPE_STUB_DECL (type) = TYPE_NAME (type);

4701     else

4702     {

4703       /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE

4704         will be the tagged type we just added to the current

4705         binding level. This fake NULL-named TYPE_DECL node helps

4706         dwarfout.c to know when it needs to output a

4707         representation of a tagged type, and it also gives us a

4708         convenient place to record the "scope start" address for

4709         the tagged type.  */

4710  

4711       tree d = build_decl (TYPE_DECL, NULL_TREE, type);

4712       TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);

4713     }

4714     timevar_pop (TV_NAME_LOOKUP);

4715   }

 

Now we have already inserted the type definition (RECORD_TYPE node) into the binding scope, tegother with the corresponding TYPE_DECL node inserted into the binding list of identifier. Below at line 1960, pushdecl just invokes add_decl_to_level to add the TYPE_DECL into names field of the cxx_scope.

 

1941   tree

1942   pushdecl_with_scope (tree x, cxx_scope *level)                                   in name-lookup.c

1943   {

1944     struct cp_binding_level *b;

1945     tree function_decl = current_function_decl;

1946  

1947     timevar_push (TV_NAME_LOOKUP);

1948     current_function_decl = NULL_TREE;

1949     if (level->kind == sk_class)

1950     {

1951       b = class_binding_level;

1952       class_binding_level = level;

1953       pushdecl_class_level (x);

1954       class_binding_level = b;

1955     }

1956     else

1957     {

1958      b = current_binding_level;

1959       current_binding_level = level;

1960       x = pushdecl (x);

1961       current_binding_level = b;

1962     }

1963     current_function_decl = function_decl;

1964     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);

1965   }

 

type_info in fact is a type series, in which compiler selects according to the class structure. And classes of the same structure would use the same type_info type, but different instances. Thus when encountering type_info usage, the compiler won’t urgently construct the instance but postpone till the front-end finally finish this compilation-unit and construct with batch. The cache for these type_infos is unemitted_tinfo_decls at line 130 in init_rtti_processing

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值