📄 cp-class.c
字号:
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_CONSTRUCTOR (variants) = TYPE_NEEDS_CONSTRUCTOR (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 has_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0; tree binfos = TYPE_BINFO_BASETYPES (t); for (i = n_baseclasses-1; i >= 0; i--) { has_abstract_virtuals |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0); if (has_abstract_virtuals) break; } if (has_abstract_virtuals) CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t); } if (n_baseclasses) { /* Notice whether this class has type conversion functions defined. Also report whether joining two types yields an ambiguity in the virtual function table, e.g., struct A { virtual int f (); }; struct B { virtual int f (); }; struct C : A, B { / * no f (); * / }; / / error, ambiguous */ tree binfo = TYPE_BINFO (t); tree binfos = BINFO_BASETYPES (binfo); int n_binfos = list_length (binfo); tree vbases = CLASSTYPE_VBASECLASSES (t), basetype; int n_vbases = list_length (vbases), j; build_mi_virtuals (n_binfos+n_vbases*n_baseclasses, max_has_virtual); /* Fill in virtual function table with values which do not come "normal"ly, i.e., those which come from virtual and/or non-leftmost base classes. */ for (i = 0; binfo; binfo = TREE_CHAIN (binfo)) { if (TREE_VIA_VIRTUAL (binfo)) /* Virtual functions from virtual baseclasses are done below. */; else if (CLASSTYPE_VSIZE (BINFO_TYPE (binfo))) { tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo)); if (flag_dossier) virtuals = TREE_CHAIN (virtuals); add_mi_virtuals (++i, virtuals); } } for (; vbases; vbases = TREE_CHAIN (vbases)) { basetype = BINFO_TYPE (vbases); if (CLASSTYPE_VSIZE (basetype)) for (j = n_baseclasses-1; j >= 0; j--) { tree this_binfo = TREE_VEC_ELT (binfos, j); if (UNIQUELY_DERIVED_FROM_P (basetype, this_binfo)) { tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (vbases)); if (flag_dossier) virtuals = TREE_CHAIN (virtuals); add_mi_virtuals (++i, virtuals); } } } 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; } report_ambiguous_mi_virtuals (n_binfos+n_vbases*n_baseclasses, t);#if 0 /* Now that we know what the virtual functiond table looks like, fix up offsets in the presence of virtual base classes. */ if (n_vbases) fixup_vbase_offsets (t);#endif } /* Need to test METHOD_VEC here in case all methods (conversions and otherwise) are inherited. */ if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE) { tree first_conversions[last_conversion_type]; tree last_conversions[last_conversion_type]; enum conversion_type conv_index; tree *tmp; int i; bzero (first_conversions, sizeof (first_conversions)); bzero (last_conversions, sizeof (last_conversions)); for (tmp = &TREE_VEC_ELT (method_vec, 1); tmp != TREE_VEC_END (method_vec); tmp += 1) { /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR]. */ if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp))) { tree fntype = TREE_TYPE (*tmp); tree return_type = TREE_TYPE (fntype); my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171); if (typecode_p (return_type, POINTER_TYPE)) { if (TYPE_READONLY (TREE_TYPE (return_type))) conv_index = constptr_conv; else conv_index = ptr_conv; } else if (typecode_p (return_type, INTEGER_TYPE)) { TYPE_HAS_INT_CONVERSION (t) = 1; conv_index = int_conv; } else if (typecode_p (return_type, REAL_TYPE)) { TYPE_HAS_REAL_CONVERSION (t) = 1; conv_index = real_conv; } else continue; if (first_conversions[(int) conv_index] == NULL_TREE) first_conversions[(int) conv_index] = *tmp; last_conversions[(int) conv_index] = *tmp; } } for (i = 0; i < (int) last_conversion_type; i++) if (first_conversions[i] != last_conversions[i]) CLASSTYPE_CONVERSION (t, i) = error_mark_node; else CLASSTYPE_CONVERSION (t, i) = first_conversions[i]; } /* If this type has constructors, force its mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. */ if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) { tree variants = t; if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) DECL_MODE (TYPE_NAME (t)) = BLKmode; while (variants) { TYPE_MODE (variants) = BLKmode; TREE_ADDRESSABLE (variants) = 1; variants = TYPE_NEXT_VARIANT (variants); } }}/* 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 TREE_CHAIN of the FUNCTION_DECLs. Friends are chained in the same way as member functions, 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 treefinish_struct_methods (t, fn_fields, nonprivate_method) tree t; tree fn_fields; int nonprivate_method;{ tree method_vec; tree 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_node (TREE_VEC); /* Room has been saved for constructors and destructors. */ current_obstack = ambient_obstack; /* Now make this a live vector. */ obstack_free (&class_obstack, method_vec); obstack_blank (&class_obstack, sizeof (struct tree_vec)); while (fn_fields) { /* NEXT Pointer, TEST Pointer, and BASE Pointer. */ tree nextp, *testp; tree fn_name = DECL_NAME (fn_fields); if (fn_name == NULL_TREE) fn_name = name; nextp = TREE_CHAIN (fn_fields); TREE_CHAIN (fn_fields) = NULL_TREE; /* Constructors are handled easily in search routines. Besides, we know we won't find any, so do not bother looking. */ if (fn_name == name && TREE_VEC_ELT (method_vec, 0) == 0) TREE_VEC_ELT (method_vec, 0) = fn_fields; else { testp = &TREE_VEC_ELT (method_vec, 0); if (*testp == NULL_TREE) testp++; while (((HOST_WIDE_INT) testp < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) && DECL_NAME (*testp) != fn_name) testp++; if ((HOST_WIDE_INT) testp < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) { tree x, prev_x; for (x = *testp; x; x = DECL_CHAIN (x)) { if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]) { /* ANSI C++ June 5 1992 WP 12.5.5.1 */ error_with_decl (fn_fields, "operator delete cannot be overloaded"); error_with_decl (x, "previous declaration here"); } if (DECL_ASSEMBLER_NAME (fn_fields) == DECL_ASSEMBLER_NAME (x)) { /* We complain about multiple destructors on sight, so we do not repeat the warning here. Friend-friend ambiguities are warned about outside this loop. */ if (! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields))) error_with_file_and_line (DECL_SOURCE_FILE (fn_fields), DECL_SOURCE_LINE (fn_fields), "ambiguous method `%s' in structure", lang_printable_name (fn_fields)); break; } prev_x = x; } if (x == 0) if (*testp) DECL_CHAIN (prev_x) = fn_fields; else *testp = fn_fields; } else { obstack_ptr_grow (&class_obstack, fn_fields); method_vec = (tree)obstack_base (&class_obstack); } } fn_fields = nextp; } 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_NAME (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) warning ("all member functions in class `%s' are private", TYPE_NAME_STRING (t)); } /* If there are constructors (and destructors), they are at the front. Place destructors at very front. Also warn if all constructors and/or destructors are private (in which case this class is effectively unusable. */ if (TYPE_HAS_DESTRUCTOR (t)) { tree dtor, prev; for (dtor = TREE_VEC_ELT (method_vec, 0); dtor; prev = dtor, dtor = DECL_CHAIN (dtor)) { if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor))) { if (TREE_PRIVATE (dtor) && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE) warning_with_decl (TYPE_NAME (t), "class `%s' only defines a private destructor and has no friends"); break; } } /* Wild parse errors can cause this to happen. */ if (dtor == NULL_TREE) TYPE_HAS_DESTRUCTOR (t) = 0; else if (dtor != TREE_VEC_ELT (method_vec, 0)) { DECL_CHAIN (prev) = DECL_CHAIN (dtor); DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0); TREE_VEC_ELT (method_vec, 0) = dtor; } } /* 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_vec) > 1) { int len = TREE_VEC_LENGTH (method_vec); tree baselink_vec = make_tree_vec (len); int any_links = 0; tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t)); for (i = 1; i < len; i++) { TREE_VEC_ELT (baselink_vec, i) = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_vec, i))); if (TREE_VEC_ELT (baselink_vec, i) != 0) any_links = 1; } if (any_links != 0) CLASSTYPE_BASELINK_VEC (t) = baselink_vec; else obstack_free (current_obstack, baselink_vec); } /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */ { tree x, last_x = NULL_TREE; int limit = TREE_VEC_LENGTH (method_vec); for (i = 1; i < limit; i++) { for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x)) { if (last_x != NULL_TREE) TREE_CHAIN (last_x) = x; last_x = x; } } /* Put ctors and dtors at the front of the list. */ x = TREE_VEC_ELT (method_vec, 0); if (x) { while (DECL_CHAIN (x)) { TREE_CHAIN (x) = DECL_CHAIN (x); x = DECL_CHAIN (x); } if (TREE_VEC_LENGTH (method_vec) > 1) TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1); else TREE_CHAIN (x) = NULL_TREE; } }#if 0 TYPE_METHODS (t) = TREE_VEC_ELT (method_vec, 0) ? TREE_VEC_ELT (method_vec, 0) : TREE_VEC_ELT (method_vec, 1);#else TYPE_METHODS (t) = method_vec;#endif return method_vec;}/* Emit error when a duplicate definition of a type is seen. Patch up. */voidduplicate_tag_error (t) tree t;{ char *err_name; tree name = TYPE_NAME (t); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); err_name = IDENTIFIER_POINTER (name); if (TREE_CODE (t) == UNION_TYPE) error ("redefinition of `union %s'", err_name); else if (TREE_CODE (t) == RECORD_TYPE) error ("redefinition of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -