📄 typeck.c
字号:
#if 0 if (component == ansi_opname[(int) TYPE_EXPR]) cp_error ("`%#T' has no such type conversion operator", basetype); else#endif cp_error ("`%#T' has no member named `%D'", basetype, 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) { cp_error ("invalid use of type decl `%#D' as expression", 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, NULL_PTR); my_friendly_assert (datum != error_mark_node, 311); } ref = fold (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; if (DECL_MUTABLE_P (field)) TREE_READONLY (ref) = 0; 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, NULL_TREE, NULL_TREE); if (rval) return rval; return build_indirect_ref (ptr, errorstring);}treebuild_indirect_ref (ptr, errorstring) tree ptr; char *errorstring;{ register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ? ptr : default_conversion (ptr)); register tree type = TREE_TYPE (pointer); if (ptr == current_class_decl) return C_C_D; if (IS_AGGR_TYPE (type)) { ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1); if (ptr) { pointer = ptr; type = TREE_TYPE (pointer); } } if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE) { if (TREE_CODE (pointer) == ADDR_EXPR && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0))) == TYPE_MAIN_VARIANT (TREE_TYPE (type))) && (TREE_READONLY (TREE_OPERAND (pointer, 0)) == TYPE_READONLY (TREE_TYPE (type))) && (TREE_THIS_VOLATILE (TREE_OPERAND (pointer, 0)) == TYPE_VOLATILE (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; } } /* `pointer' won't be an error_mark_node if we were given a pointer to member, so it's cool to check for this here. */ else if (TYPE_PTRMEMFUNC_P (type)) error ("invalid use of `%s' on pointer to member function", errorstring); else if (TREE_CODE (type) == RECORD_TYPE && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))) error ("cannot dereference signature pointer/reference"); 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 = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE); if (rval) return rval; return build_array_ref (array, index);}treebuild_array_ref (array, idx) tree array, idx;{ tree itype; if (idx == 0) { error ("subscript missing in array reference"); return error_mark_node; } if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (idx) == error_mark_node) return error_mark_node; itype = TREE_TYPE (idx); 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 (idx)) == char_type_node) warning ("array subscript has type `char'"); /* Apply default promotions *after* noticing character types. */ idx = default_conversion (idx); if (TREE_CODE (TREE_TYPE (idx)) != 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 (idx) != 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; } /* An array that is indexed by a constant value which is not within the array bounds cannot be stored in a register either; because we would get a crash in store_bit_field/extract_bit_field when trying to access a non-existent part of the register. */ if (TREE_CODE (idx) == INTEGER_CST && TYPE_VALUES (TREE_TYPE (array)) && ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array)))) { if (mark_addressable (array) == 0) return error_mark_node; } if (pedantic && !lvalue_p (array)) pedwarn ("ANSI C++ forbids subscripting non-lvalue array"); /* Note in C++ it is valid to subscript a `register' array, since it is valid to take the address of something with that storage specification. */ if (extra_warnings) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) warning ("subscripting array declared `register'"); } type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); rval = build (ARRAY_REF, type, array, idx); /* 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 (idx); /* 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;{ tree type; int is_method; if (function == error_mark_node) return error_mark_node; type = TREE_TYPE (function); 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 || TYPE_PTRMEMFUNC_P (type)); /* Handle methods, friends, and overloaded functions, respectively. */ if (is_method) { if (TREE_CODE (function) == FUNCTION_DECL) { if (DECL_NAME (function)) function = DECL_NAME (function); else function = TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function)); } else if (TREE_CODE (function) == TREE_LIST) {#if 0 if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST) function = TREE_PURPOSE (TREE_VALUE (function)); else function = TREE_PURPOSE (function);#else my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312); function = TREE_PURPOSE (function);#endif } else if (TREE_CODE (function) != IDENTIFIER_NODE) { if (TREE_CODE (function) == OFFSET_REF) { if (TREE_OPERAND (function, 0)) decl = TREE_OPERAND (function, 0); } /* Call via a pointer to member function. */ if (decl == NULL_TREE) { error ("pointer to member function called, but not in class scope"); return error_mark_node; } /* What other type of POINTER_TYPE could this be? */ if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function)) && TREE_CODE (function) != OFFSET_REF) function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, function); goto do_x_function; } /* this is an abbreviated method call. must go through here in case it is a virtual function. @@ Perhaps this could be optimized. */ if (decl == NULL_TREE) { if (current_class_type == NULL_TREE) { error ("object missing in call to method `%s'", IDENTIFIER_POINTER (function)); return error_mark_node; } /* Yow: call from a static member function. */ decl = build1 (NOP_EXPR, build_pointer_type (current_class_type), error_mark_node); decl = build_indirect_ref (decl, NULL_PTR); } return build_method_call (decl, function, params, NULL_TREE, LOOKUP_NORMAL); } else if (TREE_CODE (function) == COMPONENT_REF && type == unknown_type_node) { /* Should we undo what was done in build_component_ref? */ if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC) /* Get the name that build_component_ref hid. */ function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1))); else function = TREE_PURPOSE (TREE_OPERAND (function, 1)); return build_method_call (decl, function, params, NULL_TREE, LOOKUP_NORMAL); } else if (TREE_CODE (function) == TREE_LIST) { if (TREE_VALUE (function) == NULL_TREE) { cp_error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?", TREE_PURPOSE (function)); return error_mark_node; } else { tree val = TREE_VALUE (function); if (TREE_CODE (val) == TEMPLATE_DECL) return build_overload_call_maybe (function, params, LOOKUP_COMPLAIN, (struct candidate *)0); else if (DECL_CHAIN (val) != NULL_TREE) return build_overload_call (function, params, LOOKUP_COMPLAIN, (struct candidate *)0); else my_friendly_abort (360); } } do_x_function: if (TREE_CODE (function) == OFFSET_REF) { /* If the component is a data element (or a virtual function), we play games here to make things work. */ tree decl_addr; if (TREE_OPERAND (function, 0)) decl = TREE_OPERAND (function, 0); else decl = C_C_D; decl_addr = build_unary_op (ADDR_EXPR, decl, 0); function = get_member_function_from_ptrfunc (&decl_addr, TREE_OPERAND (function, 1)); params = tree_cons (NULL_TREE, decl_addr, params); return build_fu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -