📄 c-typeck.c
字号:
if (t1 == 0 && t2 == 0) return 1; /* If one parmlist is shorter than the other, they fail to match. */ if (t1 == 0 || t2 == 0) return 0; if (! comptypes (TREE_VALUE (t1), TREE_VALUE (t2))) return 0; t1 = TREE_CHAIN (t1); t2 = TREE_CHAIN (t2); }}/* Return 1 if PARMS specifies a fixed number of parameters and none of their types is affected by default promotions. */intcompparms1 (parms) tree parms;{ register tree t; for (t = parms; t; t = TREE_CHAIN (t)) { register tree type = TREE_VALUE (t); if (TREE_CHAIN (t) == 0 && type != void_type_node) return 0; if (type == float_type_node) return 0; if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) return 0; } return 1;}/* Return an unsigned type the same as TYPE in other respects. */treeunsigned_type (type) tree type;{ if (type == signed_char_type_node || type == char_type_node) return unsigned_char_type_node; if (type == integer_type_node) return unsigned_type_node; if (type == short_integer_type_node) return short_unsigned_type_node; if (type == long_integer_type_node) return long_unsigned_type_node; if (type == long_long_integer_type_node) return long_long_unsigned_type_node; return type;}/* Return a signed type the same as TYPE in other respects. */treesigned_type (type) tree type;{ if (type == unsigned_char_type_node || type == char_type_node) return signed_char_type_node; if (type == unsigned_type_node) return integer_type_node; if (type == short_unsigned_type_node) return short_integer_type_node; if (type == long_unsigned_type_node) return long_integer_type_node; if (type == long_long_unsigned_type_node) return long_long_integer_type_node; return type;}/* Return a type the same as TYPE except unsigned or signed according to UNSIGNEDP. */treesigned_or_unsigned_type (unsignedp, type) int unsignedp; tree type;{ if (TREE_CODE (type) != INTEGER_TYPE) return type; if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); return type;}/* Return an integer type with BITS bits of precision, that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */treetype_for_size (bits, unsignedp) int bits; int unsignedp;{ if (bits <= TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (bits <= TYPE_PRECISION (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; if (bits <= TYPE_PRECISION (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; if (bits <= TYPE_PRECISION (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; if (bits <= TYPE_PRECISION (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); return 0;}treeget_floating_type (mode) enum machine_mode mode;{ if (mode == TYPE_MODE (float_type_node)) return float_type_node; if (mode == TYPE_MODE (double_type_node)) return double_type_node; if (mode == TYPE_MODE (long_double_type_node)) return long_double_type_node; abort ();}treec_sizeof (type) tree type;{ enum tree_code code = TREE_CODE (type); if (code == FUNCTION_TYPE) { if (pedantic || warn_pointer_arith) warning ("sizeof applied to a function type"); return build_int (1); } if (code == VOID_TYPE) { if (pedantic || warn_pointer_arith) warning ("sizeof applied to a void type"); return build_int (1); } /* Convert in case a char is more than one unit. */ return convert_units (size_in_bytes (type), BITS_PER_UNIT, TYPE_PRECISION (char_type_node));}treec_sizeof_nowarn (type) tree type;{ enum tree_code code = TREE_CODE (type); if (code == FUNCTION_TYPE || code == VOID_TYPE) return build_int (1); /* Convert in case a char is more than one unit. */ return convert_units (size_in_bytes (type), BITS_PER_UNIT, TYPE_PRECISION (char_type_node));}/* Implement the __alignof keyword: Return the minimum required alignment of TYPE, measured in bytes. */treec_alignof (type) tree type;{ enum tree_code code = TREE_CODE (type); if (code == FUNCTION_TYPE) return build_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (code == VOID_TYPE) return build_int (1); return build_int (TYPE_ALIGN (type) / BITS_PER_UNIT);}/* Return either DECL or its known constant value (if it has one). */static treedecl_constant_value (decl) tree decl;{ if (! TREE_PUBLIC (decl) /* Don't change a variable array bound or initial value to a constant in a place where a variable is invalid. */ && current_function_decl != 0 && ! pedantic && ! TREE_THIS_VOLATILE (decl) && DECL_INITIAL (decl) != 0 && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK /* 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_LITERAL (DECL_INITIAL (decl)) /* Check for cases where this is sub-optimal, even though valid. */ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR && DECL_MODE (decl) != BLKmode) return DECL_INITIAL (decl); return decl;}/* Perform default promotions for C data used in expressions. Arrays and functions are converted to pointers; enumeral types or short or char, to int. In addition, manifest constants symbols are replaced by their values. */treedefault_conversion (exp) tree exp;{ register tree dt = TREE_TYPE (exp); register enum tree_code form = TREE_CODE (dt); 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)) exp = decl_constant_value (exp); /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since EXP is being used in non-lvalue context. */ if (TREE_CODE (exp) == NOP_EXPR && TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))) exp = TREE_OPERAND (exp, 0); if (form == ENUMERAL_TYPE || (form == INTEGER_TYPE && (TYPE_PRECISION (dt) < TYPE_PRECISION (integer_type_node)))) { /* Traditionally, unsignedness is preserved in default promotions. */ if (flag_traditional && TREE_UNSIGNED (dt)) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } if (flag_traditional && dt == float_type_node) return convert (double_type_node, exp); if (form == VOID_TYPE) { error ("void value not ignored as it ought to be"); return error_mark_node; } if (form == FUNCTION_TYPE) { return build_unary_op (ADDR_EXPR, exp, 0); } if (form == ARRAY_TYPE) { register tree adr; tree restype = TREE_TYPE (dt); 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 (TREE_READONLY (exp) || TREE_THIS_VOLATILE (exp)) restype = c_build_type_variant (restype, TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); 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 = build (ADDR_EXPR, ptrtype, exp); if (mark_addressable (exp) == 0) return error_mark_node; TREE_LITERAL (adr) = staticp (exp); TREE_VOLATILE (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 basename = datum; register tree basetype = TREE_TYPE (basename); register enum tree_code form = TREE_CODE (basetype); register tree field = NULL; register tree ref; /* First, see if there is a field or component with name COMPONENT. */ if (form == RECORD_TYPE || form == UNION_TYPE) { if (TYPE_SIZE (basetype) == 0) { incomplete_type_error (0, basetype); return error_mark_node; } /* Look up component name in the structure type definition. */ for (field = TYPE_FIELDS (basetype); field; field = TREE_CHAIN (field)) { if (DECL_NAME (field) == component) break; } if (!field) { error (form == 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), basename, field); if (TREE_READONLY (basename) || TREE_READONLY (field)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (basename) || TREE_VOLATILE (field)) TREE_THIS_VOLATILE (ref) = 1; return ref; } else if (form != ERROR_MARK) error ("request for member `%s' in something not a structure or union", IDENTIFIER_POINTER (component)); return error_mark_node;}/* 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. */treebuild_indirect_ref (ptr, errorstring) tree ptr; char *errorstring;{ register tree pointer = default_conversion (ptr); register tree dt = TREE_TYPE (pointer); if (TREE_CODE (dt) == POINTER_TYPE) if (TREE_CODE (pointer) == ADDR_EXPR && (TREE_TYPE (TREE_OPERAND (pointer, 0)) == TREE_TYPE (dt))) return TREE_OPERAND (pointer, 0); else { tree t = TREE_TYPE (dt); register tree ref = build (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); if (TREE_CODE (t) == VOID_TYPE || (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)) { error ("dereferencing pointer to incomplete type"); return error_mark_node; } TREE_READONLY (ref) = TREE_READONLY (t); TREE_VOLATILE (ref) = TREE_VOLATILE (t) || TREE_VOLATILE (pointer); TREE_THIS_VOLATILE (ref) = TREE_VOLATILE (t); return ref; } else if (TREE_CODE (pointer) != ERROR_MARK) error ("invalid type argument of `%s'", errorstring); 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). */treebuild_array_ref (array, index) tree array, index;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -