Studying note of GCC-3.4.6 source (63)

4.3.1.7.7.            C++ components with C++ linkage
4.3.1.7.7.1.      bad_alloc

current_lang_name indicates the language of the program, now it is updated to the identifier of C++ language. It determines the linkage of identifiers. For example, C++’s identifier has its name mangled, but not does C’s identifier.

 

cxx_init_decl_processing (continue)

 

3080     /* Now, C++.  */

3081     current_lang_name = lang_name_cplusplus;

3082  

3083     {

3084       tree bad_alloc_id;

3085       tree bad_alloc_type_node;

3086       tree bad_alloc_decl;

3087       tree newtype, deltype;

3088       tree ptr_ftype_sizetype;

3089  

3090       push_namespace (std_identifier);

3091       bad_alloc_id = get_identifier ("bad_alloc");

3092       bad_alloc_type_node = make_aggr_type (RECORD_TYPE);

3093       TYPE_CONTEXT (bad_alloc_type_node) = current_namespace ;

3094       bad_alloc_decl

3095         = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);

3096       DECL_CONTEXT (bad_alloc_decl) = current_namespace ;

3097       TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;

3098       pop_namespace ();

 

For C++, a very important operator new is offered within std namespace which is replacement for malloc in C. For the standard behavor of this operator, if no memory allocated exception std::bad_alloc will be thrown. Below bad_alloc type will be created, but it is somewhat like placeholder, because this is an empty type definition, not the real definition. Later if user uses bad_alloc (for example invoking new operator), by including header file <new>, the real bad_alloc definition will be parsed to generate the final correct node; while if nowhere to use bad_alloc , this fake definition will be left untouched.

 

859    tree

860    make_aggr_type (enum tree_code code)                                                           in lex.c

861    {

862      tree t = cxx_make_type (code);

863   

864      if (IS_AGGR_TYPE_CODE (code))

865        SET_IS_AGGR_TYPE (t, 1);

866   

867      return t;

868    }

 

Notice that the aggregate type (class/struct/union) created by make_aggr_type hasn’t any field. It is just an empty object definition.

 

808    tree

809    cxx_make_type (enum tree_code code)                                                             in lex.c

810    {

811       tree t = make_node (code);

812   

813      /* Create lang_type structure.  */

814      if (IS_AGGR_TYPE_CODE (code)

815          || code == BOUND_TEMPLATE_TEMPLATE_PARM)

816      {

817        struct lang_type *pi;

818   

819        pi = ggc_alloc_cleared (sizeof (struct lang_type));

820   

821        TYPE_LANG_SPECIFIC (t) = pi;

822        pi->u.c.h.is_lang_type_class = 1;

823   

824    #ifdef GATHER_STATISTICS

825        tree_node_counts [(int)lang_type] += 1;

826        tree_node_sizes [(int)lang_type] += sizeof (struct lang_type);

827    #endif

828      }

829   

830      /* Set up some flags that give proper default behavior.  */

831      if (IS_AGGR_TYPE_CODE (code))

832      {

833        SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown );

834        CLASSTYPE_INTERFACE_ONLY (t) = interface_only ;

835   

836        /* Make sure this is laid out, for ease of use later. In the

837          presence of parse errors, the normal was of assuring this

838          might not ever get executed, so we lay it out *immediately*.  */

839        build_pointer_type (t);

840      }

841      else

842        /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But,

843          TYPE_ALIAS_SET is initialized to -1 by default, so we must

844          clear it here.  */

845        TYPE_ALIAS_SET (t) = 0;

846   

847      /* We need to allocate a TYPE_BINFO even for TEMPLATE_TYPE_PARMs

848        since they can be virtual base types, and we then need a

849        canonical binfo for them. Ideally, this would be done lazily for

850        all types.  */

851      if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM

852          || code == BOUND_TEMPLATE_TEMPLATE_PARM

853          || code == TYPENAME_TYPE)

854        TYPE_BINFO (t) = make_binfo (size_zero_node, t, NULL_TREE, NULL_TREE);

855   

856      return t;

857    }

 

For language supporting object oriented programing, the aggregate type (struct/class/union in C++ for example) must find a way to record the relationship among it, its derived sub-classes and its inherited base-classes. It is the binfo node in the type. Here as we have mentioned, the binfo node created here is also empty.

Also notice that, this created fake bad_alloc node is not inserted into the namespace really, but set this node’s context by the namespace. It is because this type is undefined and not usable.

4.3.1.7.7.2.      Details of binfo and basetype

In C++, non-virtual drivation always leads to layout as following, for example X derives from Y, then Y from Z.

Figure 39 : layout with non-virtual inheritage

While for virtual drivation, for example X derives from Y, then Y virtually from Z. The layout will look like:

Studying note of GCC-3.4.6 source (63)_第1张图片

Figure 40 : layout with virtual inheritage

A basetype means a particular usage of a data type for inheritance in another type. Each such basetype usage has its own binfo object to describe it. The binfo object is a TREE_VEC node. Inheritance is represented by the binfo nodes allocated for a given type. For example, given types X and Y, such that Y is inherited by X, 3 binfo nodes will be allocated: one for describing the binfo properties of X, similarly one for Y, and one for describing the binfo properties of Y as a base type for X. Thus, given a pointer to class X, one can get a pointer to the binfo of Y acting as a basetype for X by looking at X's binfo's basetypes .

Studying note of GCC-3.4.6 source (63)_第2张图片

Figure 41 : relation of binfos

The content of binfo as TREE_VEC for C++ is (content enclosed by [] indicates the macros to access the fields):

Pos 0: [BINFO_INHERITANCE_CHAIN ] Slot used to build a chain that represents a use of inheritance. For example, if X is derived from Y, and Y is derived from Z, then this field can be used to link the binfo node for X to the binfo node for X's Y to represent the use of inheritance from X to Y. Similarly, this slot of the binfo node for X's Y can point to the Z from which Y is inherited (in X's inheritance hierarchy). In this fashion, one can represent and traverse specific uses of inheritance using the binfo nodes themselves (instead of consing new space pointing to binfo nodes). It is up to the language-dependent front-ends to maintain this information as necessary.

Pos 1: [BINFO_OFFSET ] The offset where this basetype appears in its containing type. The slot holds the offset (in bytes) from the base of the complete object to the base of the part of the object that is allocated on behalf of this type. This is always 0 except when there are multiple inheritances.

Pos 2: [BINFO_VTABLE ] The virtual function table belonging to this basetype . Virtual function tables provide a mechanism for run-time method dispatching. The entries of a virtual function table are language-dependent.

Pos 3: [BINFO_VIRTUALS ] The virtual functions in the virtual function table. It is a tree_list that is used as an initial approximation for building a virtual function table for this basetype.

Pos 4: [BINFO_BASETYPES ] A vector of binfos for the direct basetypes inherited by this basetype . If this basetype describes type D as inherited in C, and if the basetypes of D are E and F, then this vector contains binfos for inheritance of E and F by C.

Pos 5: [BINFO_VPTR_FIELD ] A binfo record describing a virtual base class, i.e., one where TREE_VIA_VIRTUAL is set, this field assists in locating the virtual base. The actual contents are language-dependent. In the C++ front-end this field is an INTEGER_CST giving an offset into the vtable where the offset to the virtual base can be found.

Pos 6: [BINFO_BASEACCESSES ] Indicates the accesses this binfo has to its bases. The values are access_public_node , access_proected_node or access_private_node . If this array is not present, public access is implied.

Pos 7: [BINFO_SUBVTT_INDEX ] The index in the VTT where this subobject's sub-VTT can be found. NULL_TREE if there is no subVTT (C++ specific).

A class requires a VTT if it has virtual bases. This holds:

1 - primary virtual pointer for complete object of the class.

2 - secondary VTTs for each direct non-virtual base of the class which requires a VTT

3 - secondary virtual pointers for each direct or indirect base of the class which has virtual bases or is reachable via a virtual path from the class.

4 - secondary VTTs for each direct or indirect virtual base of the class.

Secondary VTTs look like complete object VTTs without part 4.

Pos 8: [BINFO_VPTR_INDEX ] The index in the VTT where the vptr for this subobject can be found. NULL_TREE if there is no secndary vptr in the VTT (C++ specific). It is the primary vptr mentioned in Pos 7 above.

Pos 9: [BINFO_PRIMARY_BASE_OF ] The binfo of which node is a primary base. It is different from BINFO_INHERITANCE_CHAIN for virtual base because a virtual base is sometimes a primary base for a class for which it is not an immediate base (C++ specific).

make_binfo is a very basic function for creating binfo. For preparing binfo for normal “large” class that appears in program, the function will be xref_basetypes which invokes make_binfo when new binfo is expected.

 

771    tree

772    make_binfo (tree offset, tree binfo, tree vtable, tree virtuals)                       in cp/tree.c

773    {

774      tree new_binfo = make_tree_vec (BINFO_LANG_ELTS);

775      tree type;

776   

777      if (TREE_CODE (binfo) == TREE_VEC)

778      {

779        type = BINFO_TYPE (binfo);

780        BINFO_DEPENDENT_BASE_P(new_binfo)=BINFO_DEPENDENT_BASE_P(binfo);

781      }

782      else

783      {

784        type = binfo;

785        binfo = NULL_TREE;

786        BINFO_DEPENDENT_BASE_P (new_binfo) = 1;

787      }

788   

789      TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);

790      BINFO_OFFSET (new_binfo) = offset;

791      BINFO_VTABLE (new_binfo) = vtable;

792      BINFO_VIRTUALS (new_binfo) = virtuals;

793   

794      if (binfo && !BINFO_DEPENDENT_BASE_P (binfo)

795          && BINFO_BASETYPES (binfo) != NULL_TREE)

796      {

797        BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));

798        /* We do not need to copy the accesses, as they are read only.  */

799        BINFO_BASEACCESSES (new_binfo) = BINFO_BASEACCESSES (binfo);

800      }

801      return new_binfo;

802    }

 

At line 786, BINFO_DEPENDENT_BASE_P marks the binfo is a dependent base, and should not be searched within the inheritance link. The examples are bad_alloc_type_node here, template type parameters, and typename types. After creating bad_alloc_type_node , it is not finished. Remember in C++, you don't have to write struct S when refer to S ; you can just use S . We accomplish this by create_implicit_typedef to create a TYPE_DECL as if the user had written typedef struct S S .

 

930    tree

931    create_implicit_typedef (tree name, tree type)                                                   in decl.c

932    {

933      tree decl;

934   

935      decl = build_decl (TYPE_DECL, name, type);

936      DECL_ARTIFICIAL (decl) = 1;

937      /* There are other implicit type declarations, like the one *within*

938        a class that allows you to write `S::S'. We must distinguish

939        amongst these.  */

940      SET_DECL_IMPLICIT_TYPEDEF_P (decl);

941      TYPE_NAME (type) = decl;

942   

943      return decl;

944    }

 

And, in the front-end, class/struct will both be created into RECORD_TYPE (that is why some C++ course acclaims that struct and class havn’t essential difference), thus at line 864 in make_aggr_type , IS_AGGR_TYPE_CODE returns true for RECORD_TYPE and UNION_TYPE.

4.3.1.7.7.2.      Operator new and delete

Exception bad_alloc though you can use it in your program, initially it just associates with operator new and new[] for C++, which is part of the standard. It needs bind bad_alloc with these operators. In section Initialize data for operators , nodes of identifiers have been created, but not nodes of declaraction. Thus at line 3100, new and new[] are created as type of void* f(size_t) .

 

cxx_init_decl_processing (continue)

 

3100       ptr_ftype_sizetype

3101         = build_function_type (ptr_type_node,

3102                            tree_cons (NULL_TREE,

3103                                     size_type_node,

3104                                     void_list_node));

3105       newtype = build_exception_variant

3106                     (ptr_ftype_sizetype, add_exception_specifier

3107                                      (NULL_TREE, bad_alloc_type_node, -1));

3108       deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);

3109       push_cp_library_fn (NEW_EXPR, newtype);

3110       push_cp_library_fn (VEC_NEW_EXPR, newtype);

3111       global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);

3112       push_cp_library_fn (VEC_DELETE_EXPR, deltype);

3113     }

 

However type void* f(size_t) is not the exact one, the correct one should be void* f(size_t) throw bad_alloc . This variant declaration is created by build_exception_variant . As a function can throw more than one kind exception, the second parameter of build_exception_variant should be a tree_list, which is prepared by add_exception_specifier .

 

1277   tree

1278   add_exception_specifier (tree list, tree spec, int complain)                           in typeck2.c

1279   {

1280     bool ok;

1281     tree core = spec;

1282     bool is_ptr;

1283     int diag_type = -1; /* none */

1284    

1285     if (spec == error_mark_node)

1286       return list;

1287    

1288     my_friendly_assert (spec && (!list || TREE_VALUE (list)), 19990317);

1289    

1290     /* [except.spec] 1, type in an exception specifier shall not be

1291       incomplete, or pointer or ref to incomplete other than pointer

1292       to cv void.  */

1293     is_ptr = TREE_CODE (core) == POINTER_TYPE;

1294     if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE)

1295       core = TREE_TYPE (core);

1296     if (complain < 0)

1297       ok = true;

1298     else if (VOID_TYPE_P (core))

1299       ok = is_ptr;

1300     else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM)

1301       ok = true;

1302     else if (processing_template_decl)

1303       ok = true;

1304     else

1305     {

1306       ok = true;

1307       /* 15.4/1 says that types in an exception specifier must be complete,

1308         but it seems more reasonable to only require this on definitions

1309         and calls. So just give a pedwarn at this point; we will give an

1310         error later if we hit one of those two cases.  */

1311       if (!COMPLETE_TYPE_P (complete_type (core)))

1312         diag_type = 2; /* pedwarn */

1313     }

1314  

1315     if (ok)

1316     {

1317       tree probe;

1318        

1319       for (probe = list; probe; probe = TREE_CHAIN (probe))

1320         if (same_type_p (TREE_VALUE (probe), spec))

1321            break ;

1322       if (!probe)

1323         list = tree_cons (NULL_TREE, spec, list);

1324     }

1325     else

1326       diag_type = 0; /* error */

1327      

1328     if (diag_type >= 0 && complain)

1329       cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);

1330  

1331     return list;

1332   }

 

As the type node is ready, it should create declaration node for the operators and push the created declarations into the “std” namespace. The library functions here have C++ linkage.

 

3370   static tree

3371   push_cp_library_fn (enum tree_code operator_code, tree type)                           in decl.c

3372   {

3373     tree fn = build_cp_library_fn (ansi_opname (operator_code),

3374                             operator_code,

3375                             type);

3376     pushdecl (fn);

3377     return fn;

3378   }

 

ansi_opname fetches node of identifier for the operator.

 

868    #define ansi_opname (CODE) /                                                                  in cp-tree.h

869      (operator_name_info [(int) (CODE)].identifier)

 

3327   static tree

3328   build_cp_library_fn (tree name, enum tree_code operator_code, tree type)           in decl.c

3329   {

3330     tree fn = build_library_fn_1 (name, operator_code, type);

3331     TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);

3332     DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);

3333     SET_DECL_LANGUAGE (fn, lang_cplusplus);

3334     set_mangled_name_for_decl (fn);

3335     return fn;

3336   }

 

set_mangled_name_for_decl above will create the mangled name for the function and set it into DECL_ASSEMBLER_NAME. Then the created FUNCTION_DECL is pushed into std namespace by pushdecl exactly as section Push the FUNCTION_DECL Into current namespace .

 

 

 

 

你可能感兴趣的:(exception,function,tree,Build,library,inheritance)