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