📄 cp-typeck.c
字号:
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it unless we are not to support things not strictly ANSI. */ switch (TREE_CODE (datum)) { case COMPOUND_EXPR: { tree value = build_component_ref (TREE_OPERAND (datum, 1), component, basetype_path, protect); return build (COMPOUND_EXPR, TREE_TYPE (value), TREE_OPERAND (datum, 0), value); } case COND_EXPR: return build_conditional_expr (TREE_OPERAND (datum, 0), build_component_ref (TREE_OPERAND (datum, 1), component, basetype_path, protect), build_component_ref (TREE_OPERAND (datum, 2), component, basetype_path, protect)); } if (code == REFERENCE_TYPE) {#if 0 /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'. @@ Maybe that is not right. */ if (TREE_REFERENCE_EXPR (datum)) datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum); else#endif datum = convert_from_reference (datum); basetype = TREE_TYPE (datum); code = TREE_CODE (basetype); } /* First, see if there is a field or component with name COMPONENT. */ if (TREE_CODE (component) == TREE_LIST) { my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309); return build (COMPONENT_REF, TREE_TYPE (component), datum, component); } if (TREE_CODE (component) == TYPE_EXPR) return build_component_type_expr (datum, component, NULL_TREE, protect); if (! IS_AGGR_TYPE_CODE (code)) { if (code != ERROR_MARK) error ("request for member `%s' in something not a class, structure or union", IDENTIFIER_POINTER (component)); return error_mark_node; } if (TYPE_SIZE (basetype) == 0) { incomplete_type_error (0, basetype); return error_mark_node; } if (TREE_CODE (component) == BIT_NOT_EXPR) { if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0)) { error_with_aggr_type (basetype, "destructor specifier `%s::~%s' must have matching names", IDENTIFIER_POINTER (TREE_OPERAND (component, 0))); return error_mark_node; } if (! TYPE_HAS_DESTRUCTOR (basetype)) { error_with_aggr_type (basetype, "type `%s' has no destructor"); return error_mark_node; } return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); } /* Look up component name in the structure type definition. */ if (CLASSTYPE_VFIELD (basetype) && DECL_NAME (CLASSTYPE_VFIELD (basetype)) == component) /* Special-case this because if we use normal lookups in an ambiguous hierarchy, the compiler will abort (because vptr lookups are not supposed to be ambiguous. */ field = CLASSTYPE_VFIELD (basetype); else { if (basetype_path == NULL_TREE) basetype_path = TYPE_BINFO (basetype); field = lookup_field (basetype_path, component, protect && ! VFIELD_NAME_P (component), 0); if (field == error_mark_node) return error_mark_node; if (field == NULL_TREE) { /* Not found as a data field, look for it as a method. If found, then if this is the only possible one, return it, else report ambiguity error. */ tree fndecls = lookup_fnfields (basetype_path, component, 1); if (fndecls) { if (TREE_CHAIN (fndecls) == NULL_TREE && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE) { enum visibility_type visibility; tree fndecl; /* Unique, so use this one now. */ basetype = TREE_PURPOSE (fndecls); fndecl = TREE_VALUE (fndecls); visibility = compute_visibility (TREE_PURPOSE (fndecls), fndecl); if (visibility == visibility_public) { if (DECL_VINDEX (fndecl) && ! resolves_to_fixed_type_p (datum, 0)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr); datum = build_indirect_ref (addr); my_friendly_assert (datum != error_mark_node, 310); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); } return fndecl; } if (visibility == visibility_protected) error_with_decl (fndecl, "member function `%s' is protected"); else error_with_decl (fndecl, "member function `%s' is private"); return error_mark_node; } else return build (COMPONENT_REF, unknown_type_node, datum, fndecls); } if (component == ansi_opname[(int) TYPE_EXPR]) error ("%s has no such type conversion operator", code == RECORD_TYPE ? "structure" : "union"); else error (code == RECORD_TYPE ? "structure has no member named `%s'" : "union has no member named `%s'", IDENTIFIER_POINTER (component)); return error_mark_node; } else if (TREE_TYPE (field) == error_mark_node) return error_mark_node; if (TREE_CODE (field) != FIELD_DECL) { if (TREE_CODE (field) == TYPE_DECL) { error ("invalid use of type decl `%s' as expression", IDENTIFIER_POINTER (DECL_NAME (field))); return error_mark_node; } if (DECL_RTL (field) != 0) assemble_external (field); TREE_USED (field) = 1; return field; } } if (DECL_FIELD_CONTEXT (field) != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); if (integer_zerop (addr)) { error ("invalid reference to NULL ptr, use ptr-to-member instead"); return error_mark_node; } addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr); datum = build_indirect_ref (addr); my_friendly_assert (datum != error_mark_node, 311); } ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field); if (TREE_READONLY (datum) || TREE_READONLY (field)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field)) TREE_THIS_VOLATILE (ref) = 1; return ref;}/* Given an expression PTR for a pointer, return an expression for the value pointed to. ERRORSTRING is the name of the operator to appear in error messages. This function may need to overload OPERATOR_FNNAME. Must also handle REFERENCE_TYPEs for C++. */treebuild_x_indirect_ref (ptr, errorstring) tree ptr; char *errorstring;{ tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr); if (rval) return rval; return build_indirect_ref (ptr, errorstring);}treebuild_indirect_ref (ptr, errorstring) tree ptr; char *errorstring;{ register tree pointer = default_conversion (ptr); register tree type = TREE_TYPE (pointer); if (ptr == current_class_decl) return C_C_D; if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE) if (TREE_CODE (pointer) == ADDR_EXPR && (TREE_TYPE (TREE_OPERAND (pointer, 0)) == TREE_TYPE (type))) return TREE_OPERAND (pointer, 0); else { tree t = TREE_TYPE (type); register tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); TREE_READONLY (ref) = TYPE_READONLY (t); TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t); TREE_SIDE_EFFECTS (ref) = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer); return ref; } else if (pointer != error_mark_node) { if (errorstring) error ("invalid type argument of `%s'", errorstring); else error ("invalid type argument"); } return error_mark_node;}/* This handles expressions of the form "a[i]", which denotes an array reference. This is logically equivalent in C to *(a+i), but we may do it differently. If A is a variable or a member, we generate a primitive ARRAY_REF. This avoids forcing the array out of registers, and can work on arrays that are not lvalues (for example, members of structures returned by functions). If INDEX is of some user-defined type, it must be converted to integer type. Otherwise, to make a compatible PLUS_EXPR, it will inherit the type of the array, which will be some pointer type. */treebuild_x_array_ref (array, index) tree array, index;{ tree rval; rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index); if (rval) return rval; return build_array_ref (array, index);}treebuild_array_ref (array, index) tree array, index;{ tree itype; if (index == 0) { error ("subscript missing in array reference"); return error_mark_node; } if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (index) == error_mark_node) return error_mark_node; itype = TREE_TYPE (index); if (IS_AGGR_TYPE (itype)) { if (TYPE_HAS_INT_CONVERSION (itype)) index = build_type_conversion (CONVERT_EXPR, integer_type_node, index, 1); else { error_with_aggr_type (itype, "type `%s' requires integer conversion for array indexing"); return error_mark_node; } } if (TREE_CODE (itype) == REFERENCE_TYPE) { index = convert_from_reference (index); itype = TREE_TYPE (index); } if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE && TREE_CODE (array) != INDIRECT_REF) { tree rval, type; /* Subscripting with type char is likely to lose on a machine where chars are signed. So warn on any machine, but optionally. Don't warn for unsigned char since that type is safe. Don't warn for signed char because anyone who uses that must have done so deliberately. */ if (warn_char_subscripts && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) warning ("array subscript has type `char'"); /* Apply default promotions *after* noticing character types. */ index = default_conversion (index); if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE) { error ("array subscript is not an integer"); return error_mark_node; } /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do address arithmetic on its address. Likewise an array of elements of variable size. */ if (TREE_CODE (index) != INTEGER_CST || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0 && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST)) { if (mark_addressable (array) == 0) return error_mark_node; } /* Note in C++ we don't bother warning about subscripting a `register' array, since it's legal in C++ to take the address of something with that storage specification. */ if (pedantic && !lvalue_p (array)) pedwarn ("ANSI C++ forbids subscripting non-lvalue array"); if (pedantic) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) pedwarn ("ANSI C++ forbids subscripting non-lvalue array"); } type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); rval = build (ARRAY_REF, type, array, index); /* Array ref is const/volatile if the array elements are or if the array is.. */ TREE_READONLY (rval) |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array))) | TREE_READONLY (array)); TREE_SIDE_EFFECTS (rval) |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array))) | TREE_SIDE_EFFECTS (array)); TREE_THIS_VOLATILE (rval) |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array))) /* This was added by rms on 16 Nov 91. It fixes vol struct foo *a; a->elts[1] in an inline function. Hope it doesn't break something else. */ | TREE_THIS_VOLATILE (array)); return require_complete_type (fold (rval)); } { tree ar = default_conversion (array); tree ind = default_conversion (index); /* Put the integer in IND to simplify error checking. */ if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) { tree temp = ar; ar = ind; ind = temp; } if (ar == error_mark_node) return ar; if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE) { error ("subscripted value is neither array nor pointer"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE) { error ("array subscript is not an integer"); return error_mark_node; } return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, ind, PLUS_EXPR), "array indexing"); }}/* Build a function call to function FUNCTION with parameters PARAMS. PARAMS is a list--a chain of TREE_LIST nodes--in which the TREE_VALUE of each node is a parameter-expression. FUNCTION's data type may be a function type or a pointer-to-function. For C++: If FUNCTION's data type is a TREE_LIST, then the tree list is the list of possible methods that FUNCTION could conceivably be. If the list of methods comes from a class, then it will be a list of lists (where each element is associated with the class that produced it), otherwise it will be a simple list (for functions overloaded in global scope). In the first case, TREE_VALUE (function) is the head of one of those lists, and TREE_PURPOSE is the name of the function. In the second case, TREE_PURPOSE (function) is the function's name directly. DECL is the class instance variable, usually CURRENT_CLASS_DECL. *//* * [eichin:19911015.1726EST] actually return a possibly incomplete * type */treebuild_x_function_call (function, params, decl) tree function, params, decl;{ extern tree build_overload_call_maybe (); tree type = TREE_TYPE (function); int is_method = ((TREE_CODE (function) == TREE_LIST && current_class_type != NULL_TREE && IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function) || TREE_CODE (function) == IDENTIFIER_NODE || TREE_CODE (type) == METHOD_TYPE || (TREE_CODE (type) == POINTER_TYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -