📄 class.c
字号:
|| TREE_CODE (x) == TYPE_DECL) { /* Hide tag decls. */ if ((TREE_CODE (field) == TYPE_DECL && DECL_ARTIFICIAL (field)) || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))) continue; cp_error_at ("duplicate field `%D' (as type and non-type)", x); } else cp_error_at ("duplicate member `%D'", x); if (prev == 0) fields = TREE_CHAIN (fields); else TREE_CHAIN (prev) = TREE_CHAIN (x); } } } } return fields;}static voiddelete_duplicate_fields (fields) tree fields;{ tree x; for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x)) TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));}/* Change the access of FDECL to ACCESS in T. Return 1 if change was legit, otherwise return 0. */static intalter_access (t, fdecl, access) tree t; tree fdecl; tree access;{ tree elem = purpose_member (t, DECL_ACCESS (fdecl)); if (elem && TREE_VALUE (elem) != access) { if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) { cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); } else error ("conflicting access specifications for field `%s', ignored", IDENTIFIER_POINTER (DECL_NAME (fdecl))); } else if (TREE_PRIVATE (fdecl)) { if (access != access_private_node) cp_error_at ("cannot make private `%D' non-private", fdecl); goto alter; } else if (TREE_PROTECTED (fdecl)) { if (access != access_protected_node) cp_error_at ("cannot make protected `%D' non-protected", fdecl); goto alter; } /* ARM 11.3: an access declaration may not be used to restrict access to a member that is accessible in the base class. */ else if (access != access_public_node) cp_error_at ("cannot reduce access of public member `%D'", fdecl); else if (elem == NULL_TREE) { alter: DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); return 1; } return 0;}/* If FOR_TYPE needs to reinitialize virtual function table pointers for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST. Returns BASE_INIT_LIST appropriately modified. */static treemaybe_fixup_vptrs (for_type, binfo, base_init_list) tree for_type, binfo, base_init_list;{ /* Now reinitialize any slots that don't fall under our virtual function table pointer. */ tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)); while (vfields) { tree basetype = VF_NORMAL_VALUE (vfields) ? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields)) : VF_BASETYPE_VALUE (vfields); tree base_binfo = get_binfo (basetype, for_type, 0); /* Punt until this is implemented. */ if (1 /* BINFO_MODIFIED (base_binfo) */) { tree base_offset = get_vfield_offset (base_binfo); if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type))) && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo))) base_init_list = tree_cons (error_mark_node, base_binfo, base_init_list); } vfields = TREE_CHAIN (vfields); } return base_init_list;}/* If TYPE does not have a constructor, then the compiler must manually deal with all of the initialization this type requires. If a base initializer exists only to fill in the virtual function table pointer, then we mark that fact with the TREE_VIRTUAL bit. This way, we avoid multiple initializations of the same field by each virtual function table up the class hierarchy. Virtual base class pointers are not initialized here. They are initialized only at the "top level" of object creation. If we initialized them here, we would have to skip a lot of work. */static voidbuild_class_init_list (type) tree type;{ tree base_init_list = NULL_TREE; tree member_init_list = NULL_TREE; /* Since we build member_init_list and base_init_list using tree_cons, backwards fields the all through work. */ tree x; tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x)) { if (TREE_CODE (x) != FIELD_DECL) continue; if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x)) || DECL_INITIAL (x) != NULL_TREE) member_init_list = tree_cons (x, type, member_init_list); } member_init_list = nreverse (member_init_list); /* We will end up doing this last. Need special marker to avoid infinite regress. */ if (TYPE_VIRTUAL_P (type)) { base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type)); if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0) TREE_VALUE (base_init_list) = NULL_TREE; TREE_ADDRESSABLE (base_init_list) = 1; } /* 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; tree rtti; char cant_have_default_ctor; char cant_have_const_ctor; char no_const_asn_ref;};/* 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_CONST_INIT_REF (basetype)) b->cant_have_const_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; 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) && 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)) { /* Ensure that this is set from at least a virtual base class. */ if (b->rtti == NULL_TREE) b->rtti = CLASSTYPE_RTTI (basetype); /* 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))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -