📄 class.c
字号:
if (!DECL_CONV_FN_P (OVL_CURRENT (fn))) /* We can insert the new function right at the SLOTth position. */ break; } if (!TREE_VEC_ELT (method_vec, slot)) /* There is nothing in the Ith slot, so we can avoid moving anything. */ ; else { /* We know the last slot in the vector is empty because we know that at this point there's room for a new function. */ bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot), (PTR) &TREE_VEC_ELT (method_vec, slot + 1), (len - slot - 1) * sizeof (tree)); TREE_VEC_ELT (method_vec, slot) = NULL_TREE; } } } if (template_class_depth (type)) /* TYPE is a template class. Don't issue any errors now; wait until instantiation time to complain. */ ; else { tree fns; /* Check to see if we've already got this method. */ for (fns = TREE_VEC_ELT (method_vec, slot); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) != TREE_CODE (method)) continue; if (TREE_CODE (method) != TEMPLATE_DECL) { /* [over.load] Member function declarations with the same name and the same parameter types cannot be overloaded if any of them is a static member function declaration. */ if (DECL_STATIC_FUNCTION_P (fn) != DECL_STATIC_FUNCTION_P (method)) { tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn)); tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method)); if (! DECL_STATIC_FUNCTION_P (fn)) parms1 = TREE_CHAIN (parms1); else parms2 = TREE_CHAIN (parms2); if (compparms (parms1, parms2)) cp_error ("`%#D' and `%#D' cannot be overloaded", fn, method); } /* Since this is an ordinary function in a non-template class, it's mangled name can be used as a unique identifier. This technique is only an optimization; we would get the same results if we just used decls_match here. */ if (DECL_ASSEMBLER_NAME (fn) != DECL_ASSEMBLER_NAME (method)) continue; } else if (!decls_match (fn, method)) continue; /* There has already been a declaration of this method or member template. */ cp_error_at ("`%D' has already been declared in `%T'", method, type); /* We don't call duplicate_decls here to merge the declarations because that will confuse things if the methods have inline definitions. In particular, we will crash while processing the definitions. */ return; } } /* Actually insert the new method. */ TREE_VEC_ELT (method_vec, slot) = build_overload (method, TREE_VEC_ELT (method_vec, slot)); /* Add the new binding. */ if (!DECL_CONSTRUCTOR_P (method) && !DECL_DESTRUCTOR_P (method)) push_class_level_binding (DECL_NAME (method), TREE_VEC_ELT (method_vec, slot)); } pop_obstacks ();}/* Subroutines of finish_struct. *//* Look through the list of fields for this struct, deleting duplicates as we go. This must be recursive to handle anonymous unions. FIELD is the field which may not appear anywhere in FIELDS. FIELD_PTR, if non-null, is the starting point at which chained deletions may take place. The value returned is the first acceptable entry found in FIELDS. Note that anonymous fields which are not of UNION_TYPE are not duplicates, they are just anonymous fields. This happens when we have unnamed bitfields, for example. */static treedelete_duplicate_fields_1 (field, fields) tree field, fields;{ tree x; tree prev = 0; if (DECL_NAME (field) == 0) { if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) return fields; for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) fields = delete_duplicate_fields_1 (x, fields); return fields; } else { for (x = fields; x; prev = x, x = TREE_CHAIN (x)) { if (DECL_NAME (x) == 0) { if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) continue; TYPE_FIELDS (TREE_TYPE (x)) = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x))); if (TYPE_FIELDS (TREE_TYPE (x)) == 0) { if (prev == 0) fields = TREE_CHAIN (fields); else TREE_CHAIN (prev) = TREE_CHAIN (x); } } else { if (DECL_NAME (field) == DECL_NAME (x)) { if (TREE_CODE (field) == CONST_DECL && TREE_CODE (x) == CONST_DECL) cp_error_at ("duplicate enum value `%D'", x); else if (TREE_CODE (field) == CONST_DECL || TREE_CODE (x) == CONST_DECL) cp_error_at ("duplicate field `%D' (as enum and non-enum)", x); else if (DECL_DECLARES_TYPE_P (field) && DECL_DECLARES_TYPE_P (x)) { if (same_type_p (TREE_TYPE (field), TREE_TYPE (x))) continue; cp_error_at ("duplicate nested type `%D'", x); } else if (DECL_DECLARES_TYPE_P (field) || DECL_DECLARES_TYPE_P (x)) { /* 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. The access to FDECL is along the path given by BINFO. Return 1 if change was legit, otherwise return 0. */static intalter_access (t, binfo, fdecl, access) tree t; tree binfo; tree fdecl; tree access;{ tree elem = purpose_member (t, DECL_ACCESS (fdecl)); if (elem) { if (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 { /* They're changing the access to the same thing they changed it to before. That's OK. */ ; } } else { enforce_access (binfo, fdecl); DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); return 1; } return 0;}/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if non-NULL, is the methods of T. The FIELDS are the fields of T. */static voidhandle_using_decl (using_decl, t, method_vec, fields) tree using_decl; tree t; tree method_vec; tree fields;{ tree ctype = DECL_INITIAL (using_decl); tree name = DECL_NAME (using_decl); tree access = TREE_PRIVATE (using_decl) ? access_private_node : TREE_PROTECTED (using_decl) ? access_protected_node : access_public_node; tree fdecl, binfo; tree flist = NULL_TREE; tree tmp; int i; int n_methods; binfo = binfo_or_else (ctype, t); if (! binfo) return; if (name == constructor_name (ctype) || name == constructor_name_full (ctype)) { cp_error_at ("using-declaration for constructor", using_decl); return; } fdecl = lookup_member (binfo, name, 0, 0); if (!fdecl) { cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype); return; } /* Functions are represented as TREE_LIST, with the purpose being the type and the value the functions. Other members come as themselves. */ if (TREE_CODE (fdecl) == TREE_LIST) /* Ignore base type this came from. */ fdecl = TREE_VALUE (fdecl); if (TREE_CODE (fdecl) == OVERLOAD) { /* We later iterate over all functions. */ flist = fdecl; fdecl = OVL_FUNCTION (flist); } name = DECL_NAME (fdecl); n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++) if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))) == name) { cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); cp_error_at (" because of local method `%#D' with same name", OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); return; } if (! DECL_LANG_SPECIFIC (fdecl)) /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */ return; for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp)) if (DECL_NAME (tmp) == name) { cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t); cp_error_at (" because of local field `%#D' with same name", tmp); return; } /* Make type T see field decl FDECL with access ACCESS.*/ if (flist) { while (flist) { if (alter_access (t, binfo, OVL_FUNCTION (flist), access) == 0) return; flist = OVL_CHAIN (flist); } } else alter_access (t, binfo, fdecl, access);}struct base_info{ int has_virtual; int max_has_virtual; 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. */static intfinish_base_struct (t, b) tree t; struct base_info *b;{ tree binfos = TYPE_BINFO_BASETYPES (t); 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); /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P here because the case of virtual functions but non-virtual dtor is handled in finish_struct_1. */ if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype) && TYPE_HAS_DESTRUCTOR (basetype)) cp_warning ("base class `%#T' has a non-virtual destructor", basetype); /* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -