📄 class.c
字号:
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); } } { 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); } } } { 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;}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); /* 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); TYPE_FIELDS (variants) = TYPE_FIELDS (t); TYPE_SIZE (variants) = TYPE_SIZE (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); if (might_have_abstract_virtuals) break; } if (might_have_abstract_virtuals) { /* We use error_mark_node from override_one_vtable to signal an artificial abstract. */ if (CLASSTYPE_ABSTRACT_VIRTUALS (t) == error_mark_node) CLASSTYPE_ABSTRACT_VIRTUALS (t) = NULL_TREE; 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)); if (TYPE_HAS_CONVERSION (basetype)) { TYPE_HAS_CONVERSION (t) = 1; TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype); TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype); } if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t)) CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1; } } /* 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; } }}/* Add FNDECL to the method_vec growing on the class_obstack. Used by finish_struct_methods. Note, FNDECL cannot be a constructor or destructor, those cases are handled by the caller. */static voidgrow_method (fndecl, method_vec_ptr) tree fndecl; tree *method_vec_ptr;{ tree method_vec = (tree)obstack_base (&class_obstack); /* Start off past the constructors and destructor. */ tree *testp = &TREE_VEC_ELT (method_vec, 2); while (testp < (tree *) obstack_next_free (&class_obstack) && (*testp == NULL_TREE || DECL_NAME (*testp) != DECL_NAME (fndecl))) testp++; if (testp < (tree *) obstack_next_free (&class_obstack)) { tree *p; for (p = testp; *p; ) p = &DECL_CHAIN (*p); *p = fndecl; } else { obstack_ptr_grow (&class_obstack, fndecl); *method_vec_ptr = (tree)obstack_base (&class_obstack); }}/* Warn about duplicate methods in fn_fields. Also compact method lists so that lookup can be made faster. Algorithm: Outer loop builds lists by method name. Inner loop checks for redundant method names within a list. 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. */treefinish_struct_methods (t, fn_fields, nonprivate_method) tree t; tree fn_fields; int nonprivate_method;{ tree method_vec; tree save_fn_fields = fn_fields; tree ctor_name = constructor_name (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); /* Now prepare to gather fn_fields into vector. */ struct obstack *ambient_obstack = current_obstack; current_obstack = &class_obstack; method_vec = make_tree_vec (2); current_obstack = ambient_obstack; /* Now make this a live vector. */ obstack_free (&class_obstack, method_vec); /* Save room for constructors and destructors. */ obstack_blank (&class_obstack, sizeof (struct tree_vec) + sizeof (struct tree *)); /* 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; 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 that a copy ctor is private, so we don't dare generate a default copy constructor for a class that has a member of this type without making sure they have access to it. */ if (fn_name == ctor_name) { tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields); tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; if (TREE_CODE (parmtype) == REFERENCE_TYPE && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t) { if (TREE_CHAIN (parmtypes) == NULL_TREE || TREE_CHAIN (parmtypes) == void_list_node || TREE_PURPOSE (TREE_CHAIN (parmtypes))) { if (TREE_PROTECTED (fn_fields)) TYPE_HAS_NONPUBLIC_CTOR (t) = 1; else if (TREE_PRIVATE (fn_fields)) TYPE_HAS_NONPUBLIC_CTOR (t) = 2; } } if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields))) { /* Destructors go in slot 1. */ DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 1); TREE_VEC_ELT (method_vec, 1) = fn_fields; } else { /* Constructors go in slot 0. */ DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0); TREE_VEC_ELT (method_vec, 0) = fn_fields; } } else if (IDENTIFIER_TYPENAME_P (fn_name)) { tree return_type = TREE_TYPE (TREE_TYPE (fn_fields)); if (typecode_p (return_type, INTEGER_TYPE) || typecode_p (return_type, BOOLEAN_TYPE) || typecode_p (return_type, ENUMERAL_TYPE)) TYPE_HAS_INT_CONVERSION (t) = 1; else if (typecode_p (return_type, REAL_TYPE)) TYPE_HAS_REAL_CONVERSION (t) = 1; grow_method (fn_fields, &method_vec); } } fn_fields = save_fn_fields; for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields)) { tree fn_name = DECL_NAME (fn_fields); if (fn_name == ctor_name || IDENTIFIER_TYPENAME_P (fn_name)) continue; if (fn_name == ansi_opname[(int) MODIFY_EXPR]) { tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields))) { if (TREE_PROTECTED (fn_fields)) TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1; else if (TREE_PRIVATE (fn_fields)) TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2; } } grow_method (fn_fields, &method_vec); } TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack) - (&TREE_VEC_ELT (method_vec, 0)); obstack_finish (&class_obstack); CLASSTYPE_METHOD_VEC (t) = method_vec; if (nonprivate_method == 0 && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE) { tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); for (i = 0; i < n_baseclasses; i++) if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) { nonprivate_method = 1; break; } if (nonprivate_method == 0 && warn_ctor_dtor_privacy) cp_warning ("all member functions in class `%T' are private", t); } /* Warn if all destructors are private (in which case this class is effectively unusable. */ if (TYPE_HAS_DESTRUCTOR (t)) { tree dtor = TREE_VEC_ELT (method_vec, 1); /* Wild parse errors can cause this to happen. */ if (dtor == NULL_TREE) TYPE_HAS_DESTRUCTOR (t) = 0; else if (TREE_PRIVATE (dtor) && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE && warn_ctor_dtor_privacy) cp_warning ("`%#T' only defines a private destructor and has no friends", t); } /* Now for each member function (except for constructors and destructors), compute where member functions of the same name reside in base classes. */ if (n_baseclasses != 0 && TREE_VEC_LENGTH (method_ve
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -