📄 gcc-func.c
字号:
tree convert (type, expr) tree type, expr;{ register tree e = expr; register enum tree_code code = TREE_CODE (type); if (type == TREE_TYPE (expr) || TREE_CODE (expr) == ERROR_MARK) return expr; if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE) { error ("void value not ignored as it ought to be"); return error_mark_node; } if (code == VOID_TYPE) return build1 (CONVERT_EXPR, type, e);#if 0 /* This is incorrect. A truncation can't be stripped this way. Extensions will be stripped by the use of get_unwidened. */ if (TREE_CODE (expr) == NOP_EXPR) return convert (type, TREE_OPERAND (expr, 0));#endif if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) return fold (convert_to_integer (type, e)); if (code == POINTER_TYPE) return fold (convert_to_pointer (type, e)); if (code == REAL_TYPE) return fold (convert_to_real (type, e)); error ("conversion to non-scalar type requested"); return error_mark_node;}tree default_conversion (exp) tree exp;{ register tree type = TREE_TYPE (exp); register enum tree_code code = TREE_CODE (type); /* Constants can be used directly unless they're not loadable. */ if (TREE_CODE (exp) == CONST_DECL) exp = DECL_INITIAL (exp); /* Replace a nonvolatile const static variable with its value. */ else if (optimize && TREE_CODE (exp) == VAR_DECL && TREE_READONLY (exp) && DECL_MODE (exp) != BLKmode) { exp = decl_constant_value (exp); type = TREE_TYPE (exp); } /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (exp) == NON_LVALUE_EXPR) exp = TREE_OPERAND (exp, 0); /* Normally convert enums to int, but convert wide enums to something wider. */ if (code == ENUMERAL_TYPE) { type = type_for_size (MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)), (flag_traditional && TREE_UNSIGNED (type))); return convert (type, exp); } if (code == INTEGER_TYPE && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) { /* Traditionally, unsignedness is preserved in default promotions. */ if (flag_traditional && TREE_UNSIGNED (type)) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } if (flag_traditional && type == float_type_node) return convert (double_type_node, exp); if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); return error_mark_node; } if (code == FUNCTION_TYPE) { return build_unary_op (ADDR_EXPR, exp, 0); } if (code == ARRAY_TYPE) { register tree adr; tree restype = TREE_TYPE (type); tree ptrtype; if (TREE_CODE (exp) == INDIRECT_REF) return convert (TYPE_POINTER_TO (restype), TREE_OPERAND (exp, 0)); if (TREE_CODE (exp) == COMPOUND_EXPR) { tree op1 = default_conversion (TREE_OPERAND (exp, 1)); return build (COMPOUND_EXPR, TREE_TYPE (op1), TREE_OPERAND (exp, 0), op1); } if (!lvalue_p (exp) && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) { error ("invalid use of non-lvalue array"); return error_mark_node; } if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) restype = c_build_type_variant (restype, TYPE_READONLY (type), TYPE_VOLATILE (type)); ptrtype = build_pointer_type (restype); if (TREE_CODE (exp) == VAR_DECL) { /* ??? This is not really quite correct in that the type of the operand of ADDR_EXPR is not the target type of the type of the ADDR_EXPR itself. Question is, can this lossage be avoided? */ adr = build1 (ADDR_EXPR, ptrtype, exp); if (mark_addressable (exp) == 0) return error_mark_node; TREE_CONSTANT (adr) = staticp (exp); TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ return adr; } /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = build_unary_op (ADDR_EXPR, exp, 1); return convert (ptrtype, adr); } return exp;}/* Make an expression to refer to the COMPONENT field of structure or union value DATUM. COMPONENT is an IDENTIFIER_NODE. */treebuild_component_ref (datum, component) tree datum, component;{ register tree type = TREE_TYPE (datum); register enum tree_code code = TREE_CODE (type); register tree field = NULL; register tree ref; /* 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); pedantic_lvalue_warning (COMPOUND_EXPR); return build (COMPOUND_EXPR, TREE_TYPE (value), TREE_OPERAND (datum, 0), value); } case COND_EXPR: pedantic_lvalue_warning (COND_EXPR); return build_conditional_expr (TREE_OPERAND (datum, 0), build_component_ref (TREE_OPERAND (datum, 1), component), build_component_ref (TREE_OPERAND (datum, 2), component)); } /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) { if (TYPE_SIZE (type) == 0) { incomplete_type_error (0, type); return error_mark_node; } /* Look up component name in the structure type definition. If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers to the field elements. Use a binary search on this array to quickly find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC will always be set for structures which have many elements. */ if (TYPE_LANG_SPECIFIC (type)) { int bot, top, half; tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0]; field = TYPE_FIELDS (type); bot = 0; top = TYPE_LANG_SPECIFIC (type)->len; while (top - bot > 1) { int cmp; half = (top - bot + 1) >> 1; field = field_array[bot+half]; cmp = (long)DECL_NAME (field) - (long)component; if (cmp == 0) break; if (cmp < 0) bot += half; else top = bot + half; } if (DECL_NAME (field_array[bot]) == component) field = field_array[bot]; else if (DECL_NAME (field) != component) field = 0; } else { for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { if (DECL_NAME (field) == component) break; } } if (!field) { error (code == RECORD_TYPE ? "structure has no member named `%s'" : "union has no member named `%s'", IDENTIFIER_POINTER (component)); return error_mark_node; } if (TREE_TYPE (field) == error_mark_node) return error_mark_node; ref = build (COMPONENT_REF, TREE_TYPE (field), 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; } else if (code != ERROR_MARK) error ("request for member `%s' in something not a structure or union", IDENTIFIER_POINTER (component)); return error_mark_node;}tree build_unary_op (code, xarg, noconvert) enum tree_code code; tree xarg; int noconvert;{ /* No default_conversion here. It causes trouble for ADDR_EXPR. */ register tree arg = xarg; register tree argtype = 0; register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); char *errstring = NULL; tree val; if (typecode == ERROR_MARK) return error_mark_node; if (typecode == ENUMERAL_TYPE) typecode = INTEGER_TYPE; switch (code) { case CONVERT_EXPR: /* This is used for unary plus, because a CONVERT_EXPR is enough to prevent anybody from looking inside for associativity, but won't generate any code. */ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) errstring = "wrong type argument to unary plus"; else if (!noconvert) arg = default_conversion (arg); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -