📄 class.c
字号:
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. */ if (! TYPE_HAS_TRIVIAL_INIT_REF (t)) { tree variants; if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) DECL_MODE (TYPE_NAME (t)) = BLKmode; for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { TYPE_MODE (variants) = BLKmode; TREE_ADDRESSABLE (variants) = 1; } }}/* Add FN to the method_vec growing on the class_obstack. Used by finish_struct_methods. */static voidgrow_method (fn, method_vec_ptr) tree fn; tree *method_vec_ptr;{ tree method_vec = (tree)obstack_base (&class_obstack); tree *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) != DECL_NAME (fn)) 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) == ansi_opname[(int) DELETE_EXPR] || DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR]) { /* ANSI C++ June 5 1992 WP 12.5.5.1 */ cp_error_at ("`%D' overloaded", fn); cp_error_at ("previous declaration as `%D' here", x); } if (DECL_ASSEMBLER_NAME (fn)==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))) cp_error_at ("ambiguous method `%#D' in structure", fn); break; } prev_x = x; } if (x == 0) { if (*testp) DECL_CHAIN (prev_x) = fn; else *testp = fn; } } else { obstack_ptr_grow (&class_obstack, fn); *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. */static treefinish_struct_methods (t, fn_fields, nonprivate_method) tree t; tree fn_fields; int nonprivate_method;{ tree method_vec; tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields); tree lastp; 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)); /* First fill in entry 0 with the constructors, and the next few with type conversion operators (if any). */ for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp)) { tree fn_name = DECL_NAME (fn_fields); if (fn_name == NULL_TREE) fn_name = name; /* 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 == 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; } } /* Constructors are handled easily in search routines. */ 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); } else { lastp = fn_fields; continue; } TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields); TREE_CHAIN (fn_fields) = NULL_TREE; } fn_fields = TREE_CHAIN (save_fn_fields); while (fn_fields) { tree nextp; 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; 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); 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) cp_warning ("all member functions in class `%T' are private", 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 && warn_ctor_dtor_privacy) cp_warning ("`%#T' only defines a private destructor and has no friends", t); 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)) { /* Let's avoid being circular about this. */ if (x == DECL_CHAIN (x)) break; 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; } } TYPE_METHODS (t) = method_vec; return method_vec;}/* Emit error when a duplicate definition of a type is seen. Patch up. */voidduplicate_tag_error (t) tree t;{ cp_error ("redefinition of `%#T'", t); cp_error_at ("previous definition here", t); /* Pretend we haven't defined this type. */ /* All of the component_decl's were TREE_CHAINed together in the parser. finish_struct_methods walks these chains and assembles all methods with the same base name into DECL_CHAINs. Now we don't need the parser chains anymore, so we unravel them. */ /* * This used to be in finish_struct, but it turns out that the * TREE_CHAIN is used by dbxout_type_methods and perhaps some other things... */ if (CLASSTYPE_METHOD_VEC(t)) { tree tv = CLASSTYPE_METHOD_VEC(t); int i, len = TREE_VEC_LENGTH (tv); for (i = 0; i < len; i++) { tree unchain = TREE_VEC_ELT (tv, i); while (unchain != NULL_TREE) { TREE_CHAIN (unchain) = NULL_TREE; unchain = DECL_CHAIN(unchain); } } } if (TYPE_LANG_SPECIFIC (t)) { tree as_list = CLASSTYPE_AS_LIST (t); tree binfo = TYPE_BINFO (t); tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t); int interface_only = CLASSTYPE_INTERFACE_ONLY (t); int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t); bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); BINFO_BASETYPES(binfo) = NULL_TREE; CLASSTYPE_AS_LIST (t) = as_list; TYPE_BINFO (t) = binfo; CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list; CLASSTYPE_INTERFACE_ONLY (t) = interface_only; SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); CLASSTYPE_VBASE_SIZE (t) = integer_zero_node; TYPE_REDEFINED (t) = 1; } TYPE_SIZE (t)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -