📄 class.c
字号:
/* Each base class which needs to have initialization of some kind gets to make such requests known here. */ for (i = n_baseclasses-1; i >= 0; i--) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree blist; /* Don't initialize virtual baseclasses this way. */ if (TREE_VIA_VIRTUAL (base_binfo)) continue; if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo))) { /* ...and the last shall come first... */ base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list); base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list); continue; } if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE) /* Nothing to initialize. */ continue; /* ...ditto... */ base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list); /* This is normally true for single inheritance. The win is we can shrink the chain of initializations to be done by only converting to the actual type we are interested in. */ if (TREE_VALUE (blist) && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC && tree_int_cst_equal (BINFO_OFFSET (base_binfo), BINFO_OFFSET (TREE_VALUE (blist)))) { if (base_init_list) { /* Does it do more than just fill in a virtual function table pointer? */ if (! TREE_ADDRESSABLE (blist)) base_init_list = build_tree_list (blist, base_init_list); /* Can we get by just with the virtual function table pointer that it fills in? */ else if (TREE_ADDRESSABLE (base_init_list) && TREE_VALUE (base_init_list) == 0) base_init_list = blist; /* Maybe, but it is not obvious as the previous case. */ else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type)) { tree last = tree_last (base_init_list); while (TREE_VALUE (last) && TREE_CODE (TREE_VALUE (last)) == TREE_LIST) last = tree_last (TREE_VALUE (last)); if (TREE_VALUE (last) == 0) base_init_list = build_tree_list (blist, base_init_list); } } else base_init_list = blist; } else { /* The function expand_aggr_init knows how to do the initialization of `basetype' without getting an explicit `blist'. */ if (base_init_list) base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list); else base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo)); } } if (base_init_list) if (member_init_list) CLASSTYPE_BASE_INIT_LIST (type) = build_tree_list (base_init_list, member_init_list); else CLASSTYPE_BASE_INIT_LIST (type) = base_init_list; else if (member_init_list) CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;}struct base_info{ int has_virtual; int max_has_virtual; int n_ancestors; tree vfield; tree vfields; char cant_have_default_ctor; char cant_have_const_ctor; char cant_synth_copy_ctor; char cant_synth_asn_ref; char no_const_asn_ref; char needs_virtual_dtor;};/* Record information about type T derived from its base classes. Store most of that information in T itself, and place the remaining information in the struct BASE_INFO. Propagate basetype offsets throughout the lattice. Note that the lattice topped by T is really a pair: it's a DAG that gives the structure of the derivation hierarchy, and it's a list of the virtual baseclasses that appear anywhere in the DAG. When a vbase type appears in the DAG, it's offset is 0, and it's children start their offsets from that point. When a vbase type appears in the list, its offset is the offset it has in the hierarchy, and its children's offsets include that offset in theirs. Returns the index of the first base class to have virtual functions, or -1 if no such base class. Note that at this point TYPE_BINFO (t) != t_binfo. */static intfinish_base_struct (t, b, t_binfo) tree t; struct base_info *b; tree t_binfo;{ tree binfos = BINFO_BASETYPES (t_binfo); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int first_vfn_base_index = -1; bzero ((char *) b, sizeof (struct base_info)); for (i = 0; i < n_baseclasses; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree basetype = BINFO_TYPE (base_binfo); /* If the type of basetype is incomplete, then we already complained about that fact (and we should have fixed it up as well). */ if (TYPE_SIZE (basetype) == 0) { int j; /* The base type is of incomplete type. It is probably best to pretend that it does not exist. */ if (i == n_baseclasses-1) TREE_VEC_ELT (binfos, i) = NULL_TREE; TREE_VEC_LENGTH (binfos) -= 1; n_baseclasses -= 1; for (j = i; j+1 < n_baseclasses; j++) TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); } if (TYPE_HAS_INIT_REF (basetype) && !TYPE_HAS_CONST_INIT_REF (basetype)) b->cant_have_const_ctor = 1; if (! TYPE_HAS_INIT_REF (basetype) || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2 && ! is_friend_type (t, basetype))) b->cant_synth_copy_ctor = 1; if (TYPE_HAS_CONSTRUCTOR (basetype) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) { b->cant_have_default_ctor = 1; if (! TYPE_HAS_CONSTRUCTOR (t)) { cp_pedwarn ("base `%T' with only non-default constructor", basetype); cp_pedwarn ("in class without a constructor"); } } if (TYPE_HAS_ASSIGN_REF (basetype) && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) b->no_const_asn_ref = 1; if (! TYPE_HAS_ASSIGN_REF (basetype) || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype) || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2 && ! is_friend_type (t, basetype))) b->cant_synth_asn_ref = 1; b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); if (! TREE_VIA_VIRTUAL (base_binfo)#if 0 /* This cannot be done, as prepare_fresh_vtable wants to modify binfos associated with vfields anywhere in the hierarchy, not just immediate base classes. Due to unsharing, the compiler might consume 3% more memory on a real program. */ && ! BINFO_OFFSET_ZEROP (base_binfo)#endif && BINFO_BASETYPES (base_binfo)) { tree base_binfos = BINFO_BASETYPES (base_binfo); tree chain = NULL_TREE; int j; /* Now unshare the structure beneath BASE_BINFO. */ for (j = TREE_VEC_LENGTH (base_binfos)-1; j >= 0; j--) { tree base_base_binfo = TREE_VEC_ELT (base_binfos, j); if (! TREE_VIA_VIRTUAL (base_base_binfo)) TREE_VEC_ELT (base_binfos, j) = make_binfo (BINFO_OFFSET (base_base_binfo), base_base_binfo, BINFO_VTABLE (base_base_binfo), BINFO_VIRTUALS (base_base_binfo), chain); chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Completely unshare potentially shared data, and update what is ours. */ propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo)); } if (! TREE_VIA_VIRTUAL (base_binfo)) CLASSTYPE_N_SUPERCLASSES (t) += 1; if (TYPE_VIRTUAL_P (basetype)) { /* If there's going to be a destructor needed, make sure it will be virtual. */ b->needs_virtual_dtor = 1; /* Don't borrow virtuals from virtual baseclasses. */ if (TREE_VIA_VIRTUAL (base_binfo)) continue; if (first_vfn_base_index < 0) { tree vfields; first_vfn_base_index = i; /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype)); vfields = b->vfields; while (vfields) { if (VF_BINFO_VALUE (vfields) == NULL_TREE || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))) { tree value = VF_BASETYPE_VALUE (vfields); if (DECL_NAME (CLASSTYPE_VFIELD (value)) == DECL_NAME (CLASSTYPE_VFIELD (basetype))) VF_NORMAL_VALUE (b->vfields) = basetype; else VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields); } vfields = TREE_CHAIN (vfields); } CLASSTYPE_VFIELD (t) = b->vfield; } else { /* Only add unique vfields, and flatten them out as we go. */ tree vfields = CLASSTYPE_VFIELDS (basetype); while (vfields) { if (VF_BINFO_VALUE (vfields) == NULL_TREE || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields))) { tree value = VF_BASETYPE_VALUE (vfields); b->vfields = tree_cons (base_binfo, value, b->vfields); if (DECL_NAME (CLASSTYPE_VFIELD (value)) == DECL_NAME (CLASSTYPE_VFIELD (basetype))) VF_NORMAL_VALUE (b->vfields) = basetype; else VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields); } vfields = TREE_CHAIN (vfields); } if (b->has_virtual == 0) { first_vfn_base_index = i; /* Update these two, now that we know what vtable we are going to extend. This is so that we can add virtual functions, and override them properly. */ BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); CLASSTYPE_VFIELD (t) = b->vfield; /* When we install the first one, set the VF_NORMAL_VALUE to be the current class, as this it is the most derived class. Hopefully, this is not set to something else later. (mrs) */ vfields = b->vfields; while (vfields) { if (DECL_NAME (CLASSTYPE_VFIELD (t)) == DECL_NAME (CLASSTYPE_VFIELD (basetype))) { VF_NORMAL_VALUE (vfields) = t; /* There should only be one of them! And it should always be found, if we get into here. (mrs) */ break; } vfields = TREE_CHAIN (vfields); } } } } } /* Must come after offsets are fixed for all bases. */ for (i = 0; i < n_baseclasses; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree basetype = BINFO_TYPE (base_binfo); if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) { cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", basetype, t); b->cant_synth_asn_ref = 1; b->cant_synth_copy_ctor = 1; } } { tree v = get_vbase_types (t_binfo); for (; v; v = TREE_CHAIN (v)) { tree basetype = BINFO_TYPE (v); if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) { if (extra_warnings) cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", basetype, t); b->cant_synth_asn_ref = 1; b->cant_synth_copy_ctor = 1; } } } { tree vfields; /* Find the base class with the largest number of virtual functions. */ for (vfields = b->vfields; vfields; vfields = TREE_CHAIN (vfields)) { if (CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)) > b->max_has_virtual) b->max_has_virtual = CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)); if (VF_DERIVED_VALUE (vfields) && CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)) > b->max_has_virtual) b->max_has_virtual = CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)); } } if (b->vfield == 0) /* If all virtual functions come only from virtual baseclasses. */ return -1; return first_vfn_base_index;}static inttypecode_p (type, code) tree type; enum tree_code code;{ return (TREE_CODE (type) == code || (TREE_CODE (type) == REFERENCE_TYPE && TREE_CODE (TREE_TYPE (type)) == code));}/* Set memoizing fields and bits of T (and its variants) for later use. MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */static voidfinish_struct_bits (t, max_has_virtual) tree t; int max_has_virtual;{ int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); tree method_vec = CLASSTYPE_METHOD_VEC (t); /* Fix up variants (if any). */ tree variants = TYPE_NEXT_VARIANT (t); while (variants) { /* These fields are in the _TYPE part of the node, not in the TYPE_LANG_SPECIFIC component, so they are not shared. */ TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t); TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t); TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t); TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t); TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t); TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t); /* Copy whatever these are holding today. */ TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); variants = TYPE_NEXT_VARIANT (variants); } if (n_baseclasses && max_has_virtual) { /* Done by `finish_struct' for classes without baseclasses. */ int might_have_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0; tree binfos = TYPE_BINFO_BASETYPES (t); for (i = n_baseclasses-1; i >= 0; i--) { might_have_abstract_virtuals |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -