📄 c-typeck.c
字号:
if (code == FUNCTION_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("sizeof applied to a function type"); return size_int (1); } if (code == VOID_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("sizeof applied to a void type"); return size_int (1); } if (code == ERROR_MARK) return size_int (1); if (TYPE_SIZE (type) == 0) { error ("sizeof applied to an incomplete type"); return size_int (0); } /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); /* size_binop does not put the constant in range, so do it now. */ if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0)) TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1; return t;}treec_sizeof_nowarn (type) tree type;{ enum tree_code code = TREE_CODE (type); tree t; if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK) return size_int (1); if (TYPE_SIZE (type) == 0) return size_int (0); /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node))); force_fit_type (t, 0); return t;}/* Compute the size to increment a pointer by. */treec_size_in_bytes (type) tree type;{ enum tree_code code = TREE_CODE (type); tree t; if (code == FUNCTION_TYPE) return size_int (1); if (code == VOID_TYPE) return size_int (1); if (code == ERROR_MARK) return size_int (1); if (TYPE_SIZE (type) == 0) { error ("arithmetic on pointer to an incomplete type"); return size_int (1); } /* Convert in case a char is more than one unit. */ t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (BITS_PER_UNIT)); force_fit_type (t, 0); return t;}/* 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 size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (code == VOID_TYPE || code == ERROR_MARK) return size_int (1); return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);}/* Implement the __alignof keyword: Return the minimum required alignment of EXPR, measured in bytes. For VAR_DECL's and FIELD_DECL's return DECL_ALIGN (which can be set from an "aligned" __attribute__ specification). */treec_alignof_expr (expr) tree expr;{ if (TREE_CODE (expr) == VAR_DECL) return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT); if (TREE_CODE (expr) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND (expr, 1))) { error ("`__alignof' applied to a bit-field"); return size_int (1); } else if (TREE_CODE (expr) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL) return size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT); if (TREE_CODE (expr) == INDIRECT_REF) { tree t = TREE_OPERAND (expr, 0); tree best = t; int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); while (TREE_CODE (t) == NOP_EXPR && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) { int thisalign; t = TREE_OPERAND (t, 0); thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); if (thisalign > bestalign) best = t, bestalign = thisalign; } return c_alignof (TREE_TYPE (TREE_TYPE (best))); } else return c_alignof (TREE_TYPE (expr));}/* 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) && TREE_READONLY (decl) && ! ITERATOR_P (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_CONSTANT (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 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 unless it is an array, in which case we must be sure that taking the address of the array produces consistent results. */ else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) { exp = decl_constant_value (exp); type = TREE_TYPE (exp); } /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as an lvalue. */ /* Do not use STRIP_NOPS here! It will remove conversions from pointer to integer and cause infinite recursion. */ while (TREE_CODE (exp) == NON_LVALUE_EXPR || (TREE_CODE (exp) == NOP_EXPR && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) 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 || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)) && TREE_UNSIGNED (type))); return convert (type, exp); } if (C_PROMOTING_INTEGER_TYPE_P (type)) { /* Traditionally, unsignedness is preserved in default promotions. Also preserve unsignedness if not really getting any wider. */ if (TREE_UNSIGNED (type) && (flag_traditional || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } if (flag_traditional && !flag_allow_single_precision && TYPE_MAIN_VARIANT (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; int constp = 0; int volatilep = 0; if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd') { constp = TREE_READONLY (exp); volatilep = TREE_THIS_VOLATILE (exp); } if (TYPE_READONLY (type) || TYPE_VOLATILE (type) || constp || volatilep) restype = c_build_type_variant (restype, TYPE_READONLY (type) || constp, TYPE_VOLATILE (type) || volatilep); 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; } 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;}/* Look up component name in the structure type definition. If this component name is found indirectly within an anonymous union, store in *INDIRECT the component which directly contains that anonymous union. Otherwise, set *INDIRECT to 0. */ static treelookup_field (type, component, indirect) tree type, component; tree *indirect;{ tree field; /* 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) { half = (top - bot + 1) >> 1; field = field_array[bot+half]; if (DECL_NAME (field) == NULL_TREE) { /* Step through all anon unions in linear fashion. */ while (DECL_NAME (field_array[bot]) == NULL_TREE) { tree anon, junk; field = field_array[bot++]; anon = lookup_field (TREE_TYPE (field), component, &junk); if (anon != NULL_TREE) { *indirect = field; return anon; } } /* Entire record is only anon unions. */ if (bot > top) return NULL_TREE; /* Restart the binary search, with new lower bound. */ continue; } if (DECL_NAME (field) == component) break; if (DECL_NAME (field) < component) 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) == NULL_TREE) { tree junk; tree anon = lookup_field (TREE_TYPE (field), component, &junk); if (anon != NULL_TREE) { *indirect = field; return anon; } } if (DECL_NAME (field) == component) break; } } *indirect = NULL_TREE; return field;}/* 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); 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), build_component_ref (TREE_OPERAND (datum, 2), component)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -