📄 c-typeck.c
字号:
} case RECORD_TYPE: return maybe_objc_comptypes (t1, t2); } return 0;}/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring their qualifiers. */static intcomp_target_types (ttl, ttr) tree ttl, ttr;{ int val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), TYPE_MAIN_VARIANT (TREE_TYPE (ttr))); if (val == 2 && pedantic) pedwarn ("types are not quite compatible"); return val;}/* Subroutines of `comptypes'. *//* Return 1 if two function types F1 and F2 are compatible. If either type specifies no argument types, the other must specify a fixed number of self-promoting arg types. Otherwise, if one type specifies only the number of arguments, the other must specify that number of self-promoting arg types. Otherwise, the argument types must match. */static intfunction_types_compatible_p (f1, f2) tree f1, f2;{ tree args1, args2; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ int val = 1; int val1; if (!(TREE_TYPE (f1) == TREE_TYPE (f2) || (val = comptypes (TREE_TYPE (f1), TREE_TYPE (f2))))) return 0; args1 = TYPE_ARG_TYPES (f1); args2 = TYPE_ARG_TYPES (f2); /* An unspecified parmlist matches any specified parmlist whose argument types don't need default promotions. */ if (args1 == 0) { if (!self_promoting_args_p (args2)) return 0; /* If one of these types comes from a non-prototype fn definition, compare that with the other type's arglist. If they don't match, ask for a warning (but no error). */ if (TYPE_ACTUAL_ARG_TYPES (f1) && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1))) val = 2; return val; } if (args2 == 0) { if (!self_promoting_args_p (args1)) return 0; if (TYPE_ACTUAL_ARG_TYPES (f2) && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2))) val = 2; return val; } /* Both types have argument lists: compare them and propagate results. */ val1 = type_lists_compatible_p (args1, args2); return val1 != 1 ? val1 : val;}/* Check two lists of types for compatibility, returning 0 for incompatible, 1 for compatible, or 2 for compatible with warning. */static inttype_lists_compatible_p (args1, args2) tree args1, args2;{ /* 1 if no need for warning yet, 2 if warning cause has been seen. */ int val = 1; int newval; while (1) { if (args1 == 0 && args2 == 0) return val; /* If one list is shorter than the other, they fail to match. */ if (args1 == 0 || args2 == 0) return 0; /* A null pointer instead of a type means there is supposed to be an argument but nothing is specified about what type it has. So match anything that self-promotes. */ if (TREE_VALUE (args1) == 0) { if (! self_promoting_type_p (TREE_VALUE (args2))) return 0; } else if (TREE_VALUE (args2) == 0) { if (! self_promoting_type_p (TREE_VALUE (args1))) return 0; } else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2)))) { /* Allow wait (union {union wait *u; int *i} *) and wait (union wait *) to be compatible. */ if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE && TYPE_NAME (TREE_VALUE (args1)) == 0 && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)), TYPE_SIZE (TREE_VALUE (args2)))) { tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (args1)); memb; memb = TREE_CHAIN (memb)) if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2))) break; if (memb == 0) return 0; } else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE && TYPE_NAME (TREE_VALUE (args2)) == 0 && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)), TYPE_SIZE (TREE_VALUE (args1)))) { tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (args2)); memb; memb = TREE_CHAIN (memb)) if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1))) break; if (memb == 0) return 0; } else return 0; } /* comptypes said ok, but record if it said to warn. */ if (newval > val) val = newval; args1 = TREE_CHAIN (args1); args2 = TREE_CHAIN (args2); }}/* Return 1 if PARMS specifies a fixed number of parameters and none of their types is affected by default promotions. */intself_promoting_args_p (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 == 0) return 0; if (TYPE_MAIN_VARIANT (type) == float_type_node) return 0; if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; } return 1;}/* Return 1 if TYPE is not affected by default promotions. */static intself_promoting_type_p (type) tree type;{ if (TYPE_MAIN_VARIANT (type) == float_type_node) return 0; if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; return 1;}/* Return an unsigned type the same as TYPE in other respects. */treeunsigned_type (type) tree type;{ tree type1 = TYPE_MAIN_VARIANT (type); if (type1 == signed_char_type_node || type1 == char_type_node) return unsigned_char_type_node; if (type1 == integer_type_node) return unsigned_type_node; if (type1 == short_integer_type_node) return short_unsigned_type_node; if (type1 == long_integer_type_node) return long_unsigned_type_node; if (type1 == 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;{ tree type1 = TYPE_MAIN_VARIANT (type); if (type1 == unsigned_char_type_node || type1 == char_type_node) return signed_char_type_node; if (type1 == unsigned_type_node) return integer_type_node; if (type1 == short_unsigned_type_node) return short_integer_type_node; if (type1 == long_unsigned_type_node) return long_integer_type_node; if (type1 == 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;}/* Compute the value of the `sizeof' operator. */treec_sizeof (type) tree type;{ enum tree_code code = TREE_CODE (type); 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. */ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (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 || 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. */ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (TYPE_PRECISION (char_type_node)));}/* Compute the size to increment a pointer by. */treec_size_in_bytes (type) tree type;{ enum tree_code code = TREE_CODE (type); 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. */ return size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (BITS_PER_UNIT));}/* 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) && 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -