📄 init.c
字号:
{ dont_use_this = 1; decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node); } else { tree olddecl = current_class_ptr; tree oldtype = TREE_TYPE (TREE_TYPE (olddecl)); if (oldtype != type) { tree newtype = build_type_variant (type, TYPE_READONLY (oldtype), TYPE_VOLATILE (oldtype)); decl = convert_force (build_pointer_type (newtype), olddecl, 0); } else decl = olddecl; } decl = build_indirect_ref (decl, NULL_PTR); if (method_name == constructor_name (type) || method_name == constructor_name_full (type)) return build_functional_cast (type, parmlist); if (t = lookup_fnfields (basetype_path, method_name, 0)) return build_method_call (decl, TREE_CODE (name) == TEMPLATE_ID_EXPR ? name : 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) { cp_error ("invalid use of non-static field `%D'", t); return error_mark_node; } decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t); } else if (TREE_CODE (t) == VAR_DECL) decl = t; else { cp_error ("invalid use of member `%D'", t); 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, NULL_TREE); return build_function_call (decl, parmlist); } else { cp_error ("no method `%T::%D'", type, 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 TYPE :: FIELD can have its address taken by saying & TYPE :: FIELD. @@ Prints out lousy diagnostics for operator <typename> @@ fields. @@ This function should be rewritten and placed in search.c. */treebuild_offset_ref (type, name) tree type, name;{ tree decl, fnfields, fields, t = error_mark_node; tree basebinfo = NULL_TREE; int dtor = 0; if (type == std_node) return do_scoped_id (name, 0); if (processing_template_decl) return build_min_nt (SCOPE_REF, type, name); /* Handle namespace names fully here. */ if (TREE_CODE (type) == IDENTIFIER_NODE && get_aggr_from_typedef (type, 0) == 0) { tree ns = lookup_name (type, 0); tree val; if (ns && TREE_CODE (ns) == NAMESPACE_DECL) { val = lookup_namespace_name (ns, name); if (val) return val; cp_error ("namespace `%D' has no member named `%D'", ns, name); return error_mark_node; } } if (type == NULL_TREE || ! is_aggr_type (type, 1)) return error_mark_node; if (TREE_CODE (name) == BIT_NOT_EXPR) { dtor = 1; name = TREE_OPERAND (name, 0); } if (name == constructor_name_full (type)) name = constructor_name (type); if (TYPE_SIZE (complete_type (type)) == 0) { if (type == current_class_type) t = IDENTIFIER_CLASS_VALUE (name); else t = NULL_TREE; if (t == 0) { cp_error ("incomplete type `%T' does not have member `%D'", type, name); return error_mark_node; } if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) { mark_used (t); 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 (current_class_type == 0 || get_base_distance (type, current_class_type, 0, &basebinfo) == -1) { basebinfo = TYPE_BINFO (type); decl = build1 (NOP_EXPR, type, error_mark_node); } else if (current_class_ptr == 0) decl = build1 (NOP_EXPR, type, error_mark_node); else decl = current_class_ref; if (constructor_name (BINFO_TYPE (basebinfo)) == name) if (dtor) name = dtor_identifier; else name = ctor_identifier; else if (dtor) my_friendly_abort (999); fnfields = lookup_fnfields (basebinfo, name, 1); fields = lookup_field (basebinfo, name, 0, 0); if (fields == error_mark_node || fnfields == error_mark_node) return error_mark_node; /* A lot of this logic is now handled in lookup_field and lookup_fnfield. */ if (fnfields) { extern int flag_save_memoized_contexts; basebinfo = TREE_PURPOSE (fnfields); /* Go from the TREE_BASELINK to the member function info. */ t = TREE_VALUE (fnfields); if (DECL_CHAIN (t) == NULL_TREE) { tree access; /* unique functions are handled easily. */ access = compute_access (basebinfo, t); if (access == access_protected_node) { cp_error_at ("member function `%#D' is protected", t); error ("in this context"); return error_mark_node; } if (access == access_private_node) { cp_error_at ("member function `%#D' is private", t); error ("in this context"); return error_mark_node; } mark_used (t); return build (OFFSET_REF, TREE_TYPE (t), decl, t); } /* 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 (basebinfo, name, 1, 0); if (t == error_mark_node) return error_mark_node; if (t == NULL_TREE) { cp_error ("`%D' is not a member of type `%T'", name, type); return error_mark_node; } if (TREE_CODE (t) == TYPE_DECL) { TREE_USED (t) = 1; return t; } /* 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) { mark_used (t); return convert_from_reference (t); } if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t)) { cp_error ("illegal pointer to bit field `%D'", t); return error_mark_node; } /* 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 `type::name' is no longer equivalent to `this->type::name', at least not until resolve_offset_ref. */ return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);}/* If a OFFSET_REF made it through to here, then it did not have its address taken. */treeresolve_offset_ref (exp) tree exp;{ tree type = TREE_TYPE (exp); tree base = NULL_TREE; tree member; tree basetype, addr; if (TREE_CODE (exp) == TREE_LIST) return build_unary_op (ADDR_EXPR, exp, 0); if (TREE_CODE (exp) == OFFSET_REF) { member = TREE_OPERAND (exp, 1); base = TREE_OPERAND (exp, 0); } else { my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214); if (TYPE_OFFSET_BASETYPE (type) != current_class_type) { error ("object missing in use of pointer-to-member construct"); return error_mark_node; } member = exp; type = TREE_TYPE (type); base = current_class_ref; } if ((TREE_CODE (member) == VAR_DECL && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE) { /* These were static members. */ if (mark_addressable (member) == 0) return error_mark_node; return member; } if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE) return member; /* Syntax error can cause a member which should have been seen as static to be grok'd as non-static. */ if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE) { if (TREE_ADDRESSABLE (member) == 0) { cp_error_at ("member `%D' is non-static but referenced as a static member", member); error ("at this point in file"); TREE_ADDRESSABLE (member) = 1; } return error_mark_node; } /* The first case is really just a reference to a member of `this'. */ if (TREE_CODE (member) == FIELD_DECL && (base == current_class_ref || (TREE_CODE (base) == NOP_EXPR && TREE_OPERAND (base, 0) == error_mark_node))) { tree basetype_path, access; if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) basetype = TYPE_OFFSET_BASETYPE (type); else basetype = DECL_CONTEXT (member); base = current_class_ptr; if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0) { error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base))); return error_mark_node; } addr = convert_pointer_to (basetype, base); access = compute_access (basetype_path, member); if (access == access_public_node) return build (COMPONENT_REF, TREE_TYPE (member), build_indirect_ref (addr, NULL_PTR), member); if (access == access_protected_node) { cp_error_at ("member `%D' is protected", member); error ("in this context"); return error_mark_node; } if (access == access_private_node) { cp_error_at ("member `%D' is private", member); error ("in this context"); return error_mark_node; } my_friendly_abort (55); } /* Ensure that we have an object. */ if (TREE_CODE (base) == NOP_EXPR && TREE_OPERAND (base, 0) == error_mark_node) addr = error_mark_node; else { /* If this is a reference to a member function, then return the address of the member function (which may involve going through the object's vtable), otherwise, return an expression for the dereferenced pointer-to-member construct. */ addr = build_unary_op (ADDR_EXPR, base, 0); } if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE) { if (addr == error_mark_node) { cp_error ("object missing in `%E'", exp); return error_mark_node; } basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member)); addr = convert_pointer_to (basetype, addr); member = cp_convert (ptrdiff_type_node, build_unary_op (ADDR_EXPR, member, 0)); /* Pointer to data members are offset by one, so that a null pointer with a real value of 0 is distinguishable from an offset of the first member of a structure. */ member = build_binary_op (MINUS_EXPR, member, cp_convert (ptrdiff_type_node, integer_one_node), 0); return build1 (INDIRECT_REF, type, build (PLUS_EXPR, build_pointer_type (type), addr, member)); } else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) { return get_member_function_from_ptrfunc (&addr, member); } my_friendly_abort (56); /* NOTREACHED */ return NULL_TREE;}/* Return either DECL or its known constant value (if it has one). */treedecl_constant_value (decl) tree decl;{ if (! TREE_THIS_VOLATILE (decl)#if 0 /* These may be necessary for C, but they break C++. */ ! TREE_PUBLIC (decl) /* Don't change a variable array bound or initial value to a constant in a place where a variable is invalid. */ && ! pedantic#endif /* 0 */ && DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node /* This is invalid if initial value is not constant. If it has either a function call, a memory reference, or a variable, then re-evaluating it could give different results. */ && TREE_CONSTANT (DECL_INITIAL (decl)) /* Check for cases where this is sub-optimal, even though valid. */ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR#if 0 /* We must allow this to work outside of functions so that static constants can be used for array sizes. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -