📄 class.c
字号:
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 (CLASSTYPE_COM_INTERFACE (basetype)) { CLASSTYPE_COM_INTERFACE (t) = 1; if (i > 0) cp_error ("COM interface type `%T' must be the leftmost base class", basetype); } else if (CLASSTYPE_COM_INTERFACE (t)) { cp_error ("COM interface type `%T' with non-COM base class `%T'", t, basetype); CLASSTYPE_COM_INTERFACE (t) = 0; } 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. */ TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); TYPE_BINFO_VIRTUALS (t) = 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. */ TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); TYPE_BINFO_VIRTUALS (t) = 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); } } } } } { 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; /* Update the rtti base if we have a non-virtual base class version of it. */ b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index))); return first_vfn_base_index;}/* 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); /* 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); TYPE_USES_PVBASES (variants) = TYPE_USES_PVBASES (t); /* Copy whatever these are holding today. */ TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); TYPE_FIELDS (variants) = TYPE_FIELDS (t); TYPE_SIZE (variants) = TYPE_SIZE (t); TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); variants = TYPE_NEXT_VARIANT (variants); } if (n_baseclasses && max_has_virtual) { /* For a class w/o baseclasses, `finish_struct' has set CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly for a class who's base classes do not have vtables. When neither of these is true, we might have removed abstract virtuals (by providing a definition), added some (by declaring new ones), or redeclared ones from a base class. We need to recalculate what's really an abstract virtual at this point (by looking in the vtables). */ CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t); } if (n_baseclasses) { /* Notice whether this class has type conversion functions defined. */ tree binfo = TYPE_BINFO (t); tree binfos = BINFO_BASETYPES (binfo); tree basetype; for (i = n_baseclasses-1; i >= 0; i--) { basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype); } } /* If this type has a copy constructor, force its mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to be passed by invisible reference and prevent it from being returned in a register. Also do this if the class has BLKmode but can still be returned in registers, since function_cannot_inline_p won't let us inline functions returning such a type. This affects the HP-PA. */ if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t) && CLASSTYPE_NON_AGGREGATE (t))) { tree variants; DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode; for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { TYPE_MODE (variants) = BLKmode; TREE_ADDRESSABLE (variants) = 1; } }}/* Issue warnings about T having private constructors, but no friends, and so forth. HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any non-private static member functions. */static voidmaybe_warn_about_overly_private_class (t) tree t;{ int has_member_fn = 0; int has_nonprivate_method = 0; tree fn; if (!warn_ctor_dtor_privacy /* If the class has friends, those entities might create and access instances, so we should not warn. */ || (CLASSTYPE_FRIEND_CLASSES (t) || DECL_FRIENDLIST (TYPE_MAIN_DECL (t))) /* We will have warned when the template was declared; there's no need to warn on every instantiation. */ || CLASSTYPE_TEMPLATE_INSTANTIATION (t)) /* There's no reason to even consider warning about this class. */ return; /* We only issue one warning, if more than one applies, because otherwise, on code like: class A { // Oops - forgot `public:' A(); A(const A&); ~A(); }; we warn several times about essentially the same problem. */ /* Check to see if all (non-constructor, non-destructor) member functions are private. (Since there are no friends or non-private statics, we can't ever call any of the private member functions.) */ for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) /* We're not interested in compiler-generated methods; they don't provide any way to call private members. */ if (!DECL_ARTIFICIAL (fn)) { if (!TREE_PRIVATE (fn)) { if (DECL_STATIC_FUNCTION_P (fn)) /* A non-private static member function is just like a friend; it can create and invoke private member functions, and be accessed without a class instance. */ return; has_nonprivate_method = 1; break; } else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn)) has_member_fn = 1; } if (!has_nonprivate_method && has_member_fn) { /* There are no non-private methods, and there's at least one private member function that isn't a constructor or destructor. (If all the private members are constructors/destructors we want to use the code below that issues error messages specifically referring to constructors/destructors.) */ int i; tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++) if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) { has_nonprivate_method = 1; break; } if (!has_nonprivate_method) { cp_warning ("all member functions in class `%T' are private", t); return; } } /* Even if some of the member functions are non-private, the class won't be useful for much if all the constructors or destructors are private: such an object can never be created or destroyed. */ if (TYPE_HAS_DESTRUCTOR (t)) { tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1); if (TREE_PRIVATE (dtor)) { cp_warning ("`%#T' only defines a private destructor and has no friends", t); return; } } if (TYPE_HAS_CONSTRUCTOR (t)) { int nonprivate_ctor = 0; /* If a non-template class does not define a copy constructor, one is defined for it, enabling it to avoid this warning. For a template class, this does not happen, and so we would normally get a warning on: template <class T> class C { private: C(); }; To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All complete non-template or fully instantiated classes have this flag set. */ if (!TYPE_HAS_INIT_REF (t)) nonprivate_ctor = 1; else for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); fn; fn = OVL_NEXT (fn)) { tree ctor = OVL_CURRENT (fn); /* Ideally, we wouldn't count copy constructors (or, in fact, any constructor that takes an argument of the class type as a parameter) because such things cannot be used to construct an instance of the class unless you already have one. But, for now at least, we're more generous. */ if (! TREE_PRIVATE (ctor)) { nonprivate_ctor = 1; break; } } if (nonprivate_ctor == 0) { cp_warning ("`%#T' only defines private constructors and has no friends", t); return; } }}/* Warn about duplicate methods in fn_fields. Also compact method lists so that lookup can be made faster. Data Structure: List of method lists. The outer list is a TREE_LIST, whose TREE_PURPOSE field is the field name and the TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN links the entire list of methods for TYPE_METHODS. Friends are chained in the same way as member functions (? TREE_CHAIN or DECL_CHAIN), but they live in the TREE_TYPE field of the outer list. That allows them to be quickly deleted, and requires no extra storage. If there are any constructors/destructors, they are moved to the front of the list. This makes pushclass more efficient. We also link each field which has shares a name with its baseclass to the head of the list of fields for that base class. This allows us to reduce search time in places like `build_method_call' to consider only reasonably likely functions. */static voidfinish_struct_methods (t) tree t;{ tree fn_fields; tree method_vec = CLASSTYPE_METHOD_VEC (t); tree ctor_name = constructor_name (t); /* First fill in entry 0 with the constructors, entry 1 with destructors, and the next few with type conversion operators (if any). */ for (fn_fields = TYPE_METHODS (t); fn_fields; fn_fields = TREE_CHAIN (fn_fields)) { tree fn_name = DECL_NAME (fn_fields); /* Clear out this flag. @@ Doug may figure out how to break @@ this with nested classes and friends. */ DECL_IN_AGGR_P (fn_fields) = 0; /* Note here th
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -