📄 typeck.c
字号:
tree tt1, tt2;{ tree best = NULL_TREE, tmp; int i; /* If one is a baseclass of another, that's good enough. */ if (UNIQUELY_DERIVED_FROM_P (tt1, tt2)) return tt1; if (UNIQUELY_DERIVED_FROM_P (tt2, tt1)) return tt2;#if 0 /* If they share a virtual baseclass, that's good enough. */ for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp)) { if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2))) return BINFO_TYPE (tmp); }#endif /* Otherwise, try to find a unique baseclass of TT1 that is shared by TT2, and follow that down. */ for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--) { tree basetype = TYPE_BINFO_BASETYPE (tt1, i); tree trial = common_base_type (basetype, tt2); if (trial) { if (trial == error_mark_node) return trial; if (best == NULL_TREE) best = trial; else if (best != trial) return error_mark_node; } } /* Same for TT2. */ for (i = CLASSTYPE_N_BASECLASSES (tt2)-1; i >= 0; i--) { tree basetype = TYPE_BINFO_BASETYPE (tt2, i); tree trial = common_base_type (tt1, basetype); if (trial) { if (trial == error_mark_node) return trial; if (best == NULL_TREE) best = trial; else if (best != trial) return error_mark_node; } } return best;}/* Subroutines of `comptypes'. *//* Return 1 if two parameter type lists PARMS1 and PARMS2 are equivalent in the sense that functions with those parameter types can have equivalent types. If either list is empty, we win. Otherwise, the two lists must be equivalent, element by element. C++: See comment above about TYPE1, TYPE2, STRICT. If STRICT == 3, it means checking is strict, but do not compare default parameter values. */intcompparms (parms1, parms2, strict) tree parms1, parms2; int strict;{ register tree t1 = parms1, t2 = parms2; /* An unspecified parmlist matches any specified parmlist whose argument types don't need default promotions. */ if (strict <= 0 && t1 == 0) return self_promoting_args_p (t2); if (strict < 0 && t2 == 0) return self_promoting_args_p (t1); while (1) { if (t1 == 0 && t2 == 0) return 1; /* If one parmlist is shorter than the other, they fail to match, unless STRICT is <= 0. */ if (t1 == 0 || t2 == 0) { if (strict > 0) return 0; if (strict < 0) return 1; if (strict == 0) return t1 && TREE_PURPOSE (t1); } if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), strict)) { if (strict > 0) return 0; if (strict == 0) return t2 == void_list_node && TREE_PURPOSE (t1); return TREE_PURPOSE (t1) || TREE_PURPOSE (t2); }#if 0 /* Default parms are not part of the type of a function. */ if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) { int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); if (cmp < 0) my_friendly_abort (113); if (cmp == 0) return 0; }#endif t1 = TREE_CHAIN (t1); t2 = TREE_CHAIN (t2); }}/* This really wants return whether or not parameter type lists would make their owning functions assignment compatible or not. */intcomp_target_parms (parms1, parms2, strict) tree parms1, parms2; int strict;{ register tree t1 = parms1, t2 = parms2; int warn_contravariance = 0; /* An unspecified parmlist matches any specified parmlist whose argument types don't need default promotions. @@@ see 13.3.3 for a counterexample... */ if (t1 == 0 && t2 != 0) { cp_pedwarn ("ANSI C++ prohibits conversion from `(%#T)' to `(...)'", parms2); return self_promoting_args_p (t2); } if (t2 == 0) return self_promoting_args_p (t1); for (; t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) { tree p1, p2; /* If one parmlist is shorter than the other, they fail to match, unless STRICT is <= 0. */ if (t1 == 0 || t2 == 0) { if (strict > 0) return 0; if (strict < 0) return 1 + warn_contravariance; return ((t1 && TREE_PURPOSE (t1)) + warn_contravariance); } p1 = TREE_VALUE (t1); p2 = TREE_VALUE (t2); if (p1 == p2) continue; if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE) || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE)) { if (strict <= 0 && (TYPE_MAIN_VARIANT (TREE_TYPE (p1)) == TYPE_MAIN_VARIANT (TREE_TYPE (p2)))) continue; /* The following is wrong for contravariance, but many programs depend on it. */ if (TREE_TYPE (p1) == void_type_node) continue; if (TREE_TYPE (p2) == void_type_node) { warn_contravariance = 1; continue; } if (IS_AGGR_TYPE (TREE_TYPE (p1))) { if (comptypes (p2, p1, 0) == 0) { if (comptypes (p1, p2, 0) != 0) warn_contravariance = 1; else return 0; } continue; } } /* Note backwards order due to contravariance. */ if (comp_target_types (p2, p1, 1) == 0) { if (comp_target_types (p1, p2, 1)) { warn_contravariance = 1; continue; } if (strict != 0) return 0;#if 0 /* What good do these cases do? */ if (strict == 0) return p2 == void_type_node && TREE_PURPOSE (t1); return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);#endif } /* Target types are compatible--just make sure that if we use parameter lists, that they are ok as well. */ if (TREE_CODE (p1) == FUNCTION_TYPE || TREE_CODE (p1) == METHOD_TYPE) switch (comp_target_parms (TYPE_ARG_TYPES (p1), TYPE_ARG_TYPES (p2), strict)) { case 0: return 0; case 1: break; case 2: warn_contravariance = 1; } if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) { int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)); if (cmp < 0) my_friendly_abort (114); if (cmp == 0) return 0; } } return 1 + warn_contravariance;}/* 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_MAIN_VARIANT (type) == float_type_node) return 0; if (type == 0) return 0; if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; } return 1;}/* Return an unsigned type the same as TYPE in other respects. C++: must make these work for type variants as well. */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 (! INTEGRAL_TYPE_P (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;}treec_sizeof (type) tree type;{ enum tree_code code = TREE_CODE (type); tree t; if (code == FUNCTION_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a function type"); return size_int (1); } if (code == METHOD_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a method type"); return size_int (1); } if (code == VOID_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids taking the sizeof a void type"); return size_int (1); } if (code == ERROR_MARK) return size_int (1); /* ARM $5.3.2: ``When applied to a reference, the result is the size of the referenced object.'' */ if (code == REFERENCE_TYPE) type = TREE_TYPE (type); /* We couldn't find anything in the ARM or the draft standard that says, one way or the other, if doing sizeof on something that doesn't have an object associated with it is correct or incorrect. For example, if you declare `struct S { char str[16]; };', and in your program do a `sizeof (S::str)', should we flag that as an error or should we give the size of it? Since it seems like a reasonable thing to do, we'll go with giving the value. */ if (code == OFFSET_TYPE) type = TREE_TYPE (type); /* @@ This also produces an error for a signature ref. In that case we should be able to do better. */ if (IS_SIGNATURE (type)) { error ("`sizeof' applied to a signature type"); return size_int (0); } 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 == METHOD_TYPE || code == VOID_TYPE || code == ERROR_MARK) return size_int (1); if (code == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_SIZE (type) == 0) {#if 0 /* ??? Tiemann, why have any diagnostic here? There is none in the corresponding function for C. */ warning ("sizeof applied to an incomplete type");#endif 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;}/* 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); tree t; if (code == FUNCTION_TYPE || code == METHOD_TYPE) return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (code == VOID_TYPE || code == ERROR_MARK) return size_int (1); /* C++: this is really correct! */ if (code == REFERENCE_TYPE) type = TREE_TYPE (type); /* @@ This also produces an error for a signature ref.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -