📄 cp-init.c
字号:
is_aggr_typedef (name, or_else) tree name;{ tree type; if (name == error_mark_node) return 0; if (! IDENTIFIER_HAS_TYPE_VALUE (name)) { if (or_else) error ("`%s' fails to be an aggregate typedef", IDENTIFIER_POINTER (name)); return 0; } type = IDENTIFIER_TYPE_VALUE (name); if (! IS_AGGR_TYPE (type)) { if (or_else) error ("type `%s' is of non-aggregate type", IDENTIFIER_POINTER (name)); return 0; } return 1;}/* This code could just as well go in `cp-class.c', but is placed here for modularity. *//* For an expression of the form CNAME :: NAME (PARMLIST), build the appropriate function call. */treebuild_member_call (cname, name, parmlist) tree cname, name, parmlist;{ tree type, t; tree method_name = name; int dtor = 0; int dont_use_this = 0; tree basetype_path, decl; if (TREE_CODE (method_name) == BIT_NOT_EXPR) { method_name = TREE_OPERAND (method_name, 0); dtor = 1; } if (TREE_CODE (cname) == SCOPE_REF) cname = resolve_scope_to_name (NULL_TREE, cname); if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1)) return error_mark_node; /* An operator we did not like. */ if (name == NULL_TREE) return error_mark_node; if (dtor) { if (! TYPE_HAS_DESTRUCTOR (IDENTIFIER_TYPE_VALUE (cname))) error ("type `%s' does not have a destructor", IDENTIFIER_POINTER (cname)); else error ("destructor specification error"); return error_mark_node; } type = IDENTIFIER_TYPE_VALUE (cname); /* No object? Then just fake one up, and let build_method_call figure out what to do. */ if (current_class_type == 0 || get_base_distance (type, current_class_type, 0, &basetype_path) == -1) dont_use_this = 1; if (dont_use_this) { basetype_path = NULL_TREE; decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); } else if (current_class_decl == 0) { dont_use_this = 1; decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); } else { decl = current_class_decl; if (TREE_TYPE (decl) != type) decl = convert (TYPE_POINTER_TO (type), decl); } if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0)) return build_method_call (decl, method_name, parmlist, basetype_path, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); if (TREE_CODE (name) == IDENTIFIER_NODE && (t = lookup_field (TYPE_BINFO (type), name, 1, 0))) { if (t == error_mark_node) return error_mark_node; if (TREE_CODE (t) == FIELD_DECL) { if (dont_use_this) { error ("invalid use of non-static field `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; } decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t); } else if (TREE_CODE (t) == VAR_DECL) decl = t; else { error ("invalid use of member `%s::%s'", IDENTIFIER_POINTER (cname), name); return error_mark_node; } if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)) && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl))) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist); return build_function_call (decl, parmlist); } else { char *err_name; if (TREE_CODE (name) == IDENTIFIER_NODE) { if (IDENTIFIER_OPNAME_P (name)) { char *op_name = operator_name_string (method_name); err_name = (char *)alloca (13 + strlen (op_name)); sprintf (err_name, "operator %s", op_name); } else err_name = IDENTIFIER_POINTER (name); } else my_friendly_abort (51); error ("no method `%s::%s'", IDENTIFIER_POINTER (cname), err_name); return error_mark_node; }}/* Build a reference to a member of an aggregate. This is not a C++ `&', but really something which can have its address taken, and then act as a pointer to member, for example CNAME :: FIELD can have its address taken by saying & CNAME :: FIELD. @@ Prints out lousy diagnostics for operator <typename> @@ fields. @@ This function should be rewritten and placed in cp-search.c. */treebuild_offset_ref (cname, name) tree cname, name;{ tree decl, type, fnfields, fields, t = error_mark_node; tree basetypes = NULL_TREE; int dtor = 0; if (TREE_CODE (cname) == SCOPE_REF) cname = resolve_scope_to_name (NULL_TREE, cname); if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1)) return error_mark_node; type = IDENTIFIER_TYPE_VALUE (cname); if (TREE_CODE (name) == BIT_NOT_EXPR) { dtor = 1; name = TREE_OPERAND (name, 0); } if (TYPE_SIZE (type) == 0) { t = IDENTIFIER_CLASS_VALUE (name); if (t == 0) { error_with_aggr_type (type, "incomplete type `%s' does not have member `%s'", IDENTIFIER_POINTER (name)); return error_mark_node; } if (TREE_CODE (t) == TYPE_DECL) { error_with_decl (t, "member `%s' is just a type declaration"); return error_mark_node; } if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) { TREE_USED (t) = 1; return t; } if (TREE_CODE (t) == FIELD_DECL) sorry ("use of member in incomplete aggregate type"); else if (TREE_CODE (t) == FUNCTION_DECL) sorry ("use of member function in incomplete aggregate type"); else my_friendly_abort (52); return error_mark_node; } if (TREE_CODE (name) == TYPE_EXPR) /* Pass a TYPE_DECL to build_component_type_expr. */ return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)), name, NULL_TREE, 1); fnfields = lookup_fnfields (TYPE_BINFO (type), name, 0); fields = lookup_field (type, name, 0, 0); if (fields == error_mark_node) return error_mark_node; if (current_class_type == 0 || get_base_distance (type, current_class_type, 0, &basetypes) == -1) { basetypes = TYPE_BINFO (type); decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname), error_mark_node); } else if (current_class_decl == 0) decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname), error_mark_node); else decl = C_C_D; if (fnfields) { basetypes = TREE_PURPOSE (fnfields); /* Go from the TREE_BASELINK to the member function info. */ t = TREE_VALUE (fnfields); if (fields) { if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t)) { error ("ambiguous member reference: member `%s' defined as both field and function", IDENTIFIER_POINTER (name)); return error_mark_node; } if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t))) ; else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields))) t = fields; else { error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice"); return error_mark_node; } } if (t == TREE_VALUE (fnfields)) { extern int flag_save_memoized_contexts; /* This does not handle visibility checking yet. */ if (DECL_CHAIN (t) == NULL_TREE || dtor) { enum visibility_type visibility; /* unique functions are handled easily. */ unique: visibility = compute_visibility (basetypes, t); if (visibility == visibility_protected) { error_with_decl (t, "member function `%s' is protected"); error ("in this context"); return error_mark_node; } if (visibility == visibility_private) { error_with_decl (t, "member function `%s' is private"); error ("in this context"); return error_mark_node; } assemble_external (t); return build (OFFSET_REF, TREE_TYPE (t), decl, t); } /* overloaded functions may need more work. */ if (cname == name) { if (TYPE_HAS_DESTRUCTOR (type) && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE) { t = DECL_CHAIN (t); goto unique; } } /* FNFIELDS is most likely allocated on the search_obstack, which will go away after this class scope. If we need to save this value for later (either for memoization or for use as an initializer for a static variable), then do so here. ??? The smart thing to do for the case of saving initializers is to resolve them before we're done with this scope. */ if (!TREE_PERMANENT (fnfields) && ((flag_save_memoized_contexts && global_bindings_p ()) || ! allocation_temporary_p ())) fnfields = copy_list (fnfields); t = build_tree_list (error_mark_node, fnfields); TREE_TYPE (t) = build_offset_type (type, unknown_type_node); return t; } } /* Now that we know we are looking for a field, see if we have access to that field. Lookup_field will give us the error message. */ t = lookup_field (basetypes, name, 1, 0); if (t == error_mark_node) return error_mark_node; if (t == NULL_TREE) { char *print_name; if (name == ansi_opname[(int) TYPE_EXPR]) { error ("type conversion operator not a member of type `%s'", IDENTIFIER_POINTER (cname)); return error_mark_node; } print_name = operator_name_string (name); /* First character of "<invalid operator>". */ if (print_name[0] == '<') error ("field `%s' is not a member of type `%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (cname)); else error ("operator `%s' is not a member of type `%s'", print_name, IDENTIFIER_POINTER (cname)); return error_mark_node; } if (TREE_CODE (t) == TYPE_DECL) { error_with_decl (t, "member `%s' is just a type declaration"); return error_mark_node; } /* static class members and class-specific enum values can be returned without further ado. */ if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) { assemble_external (t); TREE_USED (t) = 1; return t; } /* static class functions too. */ if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) my_friendly_abort (53); /* In member functions, the form `cname::name' is no longer equivalent to `this->cname::name'. */ return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);}/* Given an object EXP and a member function reference MEMBER, return the address of the actual member function. */treeget_member_function (exp_addr_ptr, exp, member) tree *exp_addr_ptr; tree exp, member;{ tree ctype = TREE_TYPE (exp); tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0)); if (TYPE_VIRTUAL_P (ctype) || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype))) { tree e0, e1, e3; tree exp_addr; /* Save away the unadulterated `this' pointer. */ exp_addr = save_expr (*exp_addr_ptr); /* Cast function to signed integer. */ e0 = build1 (NOP_EXPR, integer_type_node, function);#ifdef VTABLE_USES_MASK /* If we are willing to limit the number of virtual functions a class may have to some *small* number, then if, for a function address, we are passed some small number, we know that it is a virtual function index, and work from there. */ e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);#else /* There is a hack here that takes advantage of twos complement arithmetic, and the fact that there are more than one UNITS to the WORD. If the high bit is set for the `function', then we pretend it is a virtual function, and the array indexing will knock this bit out the top, leaving a valid index. */ if (UNITS_PER_WORD <= 1) my_friendly_abort (54); e1 = build (GT_EXPR, integer_type_node, e0, integer_zero_node); e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr, build_tree_list (NULL_TREE, e1))); e1 = save_expr (e1);#endif if (TREE_SIDE_EFFECTS (*exp_addr_ptr)) { exp = build_indirect_ref (exp_addr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -