📄 typeck.c
字号:
rval = build_function_type (valtype, p1); if (raises) rval = build_exception_variant (rval, raises); return build_type_attribute_variant (rval, attributes); } rval = build_function_type (valtype, commonparms (p1, p2)); rval = build_exception_variant (rval, raises); return build_type_attribute_variant (rval, attributes); } case RECORD_TYPE: case UNION_TYPE: my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1 && TYPE_MAIN_VARIANT (t2) == t2, 306); if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2)) return build_type_attribute_variant (t1, attributes); else if (binfo_or_else (t2, t1)) return build_type_attribute_variant (t2, attributes); else compiler_error ("common_type called with uncommon aggregate types"); case METHOD_TYPE: if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) { /* Get this value the long way, since TYPE_METHOD_BASETYPE is just the main variant of this. */ tree basetype; tree raises, t3; tree b1 = TYPE_OFFSET_BASETYPE (t1); tree b2 = TYPE_OFFSET_BASETYPE (t2); if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)) basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2))); else { if (binfo_or_else (b2, b1) == NULL_TREE) compiler_error ("common_type called with uncommon method types"); basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1))); } raises = TYPE_RAISES_EXCEPTIONS (t1); /* If this was a member function type, get back to the original type of type member function (i.e., without the class instance variable up front. */ t1 = build_function_type (TREE_TYPE (t1), TREE_CHAIN (TYPE_ARG_TYPES (t1))); t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2))); t3 = common_type (t1, t2); t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3)); t1 = build_exception_variant (t3, raises); } else compiler_error ("common_type called with uncommon method types"); return build_type_attribute_variant (t1, attributes); case OFFSET_TYPE: if (TREE_TYPE (t1) == TREE_TYPE (t2)) { tree b1 = TYPE_OFFSET_BASETYPE (t1); tree b2 = TYPE_OFFSET_BASETYPE (t2); if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)) return build_type_attribute_variant (t2, attributes); else if (binfo_or_else (b2, b1)) return build_type_attribute_variant (t1, attributes); } compiler_error ("common_type called with uncommon member types"); default: return build_type_attribute_variant (t1, attributes); }}/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */intcompexcepttypes (t1, t2, strict) tree t1, t2; int strict;{ return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);}static intcomp_array_types (cmp, t1, t2, strict) register int (*cmp)(); tree t1, t2; int strict;{ tree d1 = TYPE_DOMAIN (t1); tree d2 = TYPE_DOMAIN (t2); /* Target types must match incl. qualifiers. */ if (!(TREE_TYPE (t1) == TREE_TYPE (t2) || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict))) return 0; /* Sizes must match unless one is missing or variable. */ if (d1 == 0 || d2 == 0 || d1 == d2 || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST) return 1; return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1)) == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2))) && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1)) == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2))) && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1)) == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2))) && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1)) == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2))));}/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. This is what ANSI C++ speaks of as "being the same". For C++: argument STRICT says we should be strict about this comparison: 2 : strict, except that if one type is a reference and the other is not, compare the target type of the reference to the type that's not a reference (ARM, p308). This is used for checking for invalid overloading. 1 : strict (compared according to ANSI C) This is used for checking whether two function decls match. 0 : <= (compared according to C++) -1: <= or >= (relaxed) Otherwise, pointers involving base classes and derived classes can be mixed as valid: i.e. a pointer to a base class may be assigned to a pointer to one of its derived classes, as per C++. A pointer to a derived class may be passed as a parameter to a function expecting a pointer to a base classes. These allowances do not commute. In this case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to be the derived class. */intcomptypes (type1, type2, strict) tree type1, type2; int strict;{ register tree t1 = type1; register tree t2 = type2; int attrval, val; /* Suppress errors caused by previously reported errors */ if (t1 == t2) return 1; /* This should never happen. */ my_friendly_assert (t1 != error_mark_node, 307); if (t2 == error_mark_node) return 0; if (strict < 0) { /* Treat an enum type as the unsigned integer type of the same width. */ if (TREE_CODE (t1) == ENUMERAL_TYPE) t1 = type_for_size (TYPE_PRECISION (t1), 1); if (TREE_CODE (t2) == ENUMERAL_TYPE) t2 = type_for_size (TYPE_PRECISION (t2), 1); if (t1 == t2) return 1; } /* Different classes of types can't be compatible. */ if (TREE_CODE (t1) != TREE_CODE (t2)) { if (strict == 2 && ((TREE_CODE (t1) == REFERENCE_TYPE) ^ (TREE_CODE (t2) == REFERENCE_TYPE))) { if (TREE_CODE (t1) == REFERENCE_TYPE) return comptypes (TREE_TYPE (t1), t2, 1); return comptypes (t1, TREE_TYPE (t2), 1); } return 0; } if (strict > 1) strict = 1; /* Qualifiers must match. */ if (TYPE_READONLY (t1) != TYPE_READONLY (t2)) return 0; if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2)) return 0; /* Allow for two different type nodes which have essentially the same definition. Note that we already checked for equality of the type type qualifiers (just above). */ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1;#ifdef COMP_TYPE_ATTRIBUTES if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2))) return 0;#else /* 1 if no need for warning yet, 2 if warning cause has been seen. */ attrval = 1;#endif /* 1 if no need for warning yet, 2 if warning cause has been seen. */ val = 0; switch (TREE_CODE (t1)) { case RECORD_TYPE: case UNION_TYPE: if (strict <= 0) goto look_hard; return 0; case OFFSET_TYPE: val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)), build_pointer_type (TYPE_OFFSET_BASETYPE (t2)), strict) && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)); break; case METHOD_TYPE: if (! compexcepttypes (t1, t2, strict)) return 0; /* This case is anti-symmetrical! One can pass a base member (or member function) to something expecting a derived member (or member function), but not vice-versa! */ val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict) && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict)); break; case POINTER_TYPE: case REFERENCE_TYPE: t1 = TREE_TYPE (t1); t2 = TREE_TYPE (t2); if (t1 == t2) { val = 1; break; } if (strict <= 0) { if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE) { int rval; look_hard: rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2); if (rval) { val = 1; break; } if (strict < 0) { val = UNIQUELY_DERIVED_FROM_P (t2, t1); break; } } return 0; } else val = comptypes (t1, t2, strict); break; case FUNCTION_TYPE: if (! compexcepttypes (t1, t2, strict)) return 0; val = ((TREE_TYPE (t1) == TREE_TYPE (t2) || comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)) && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict)); break; case ARRAY_TYPE: /* Target types must match incl. qualifiers. */ val = comp_array_types (comptypes, t1, t2, strict); break; case TEMPLATE_TYPE_PARM: return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2); case UNINSTANTIATED_P_TYPE: if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2)) return 0; { int i = TREE_VEC_LENGTH (UPT_PARMS (t1)); tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0); tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0); while (i--) { if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't') { if (! comptypes (p1[i], p2[i], 1)) return 0; } else { if (simple_cst_equal (p1[i], p2[i]) <= 0) return 0; } } } return 1; } return attrval == 2 && val == 1 ? 2 : val;}/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring their qualifiers. NPTRS is the number of pointers we can strip off and keep cool. This is used to permit (for aggr A, aggr B) A, B* to convert to A*, but to not permit B** to convert to A**. */intcomp_target_types (ttl, ttr, nptrs) tree ttl, ttr; int nptrs;{ ttl = TYPE_MAIN_VARIANT (ttl); ttr = TYPE_MAIN_VARIANT (ttr); if (ttl == ttr) return 1; if (TREE_CODE (ttr) != TREE_CODE (ttl)) return 0; if (TREE_CODE (ttr) == POINTER_TYPE) { ttl = TREE_TYPE (ttl); ttr = TREE_TYPE (ttr); if (nptrs > 0) { if (TREE_CODE (ttl) == VOID_TYPE && TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE && TREE_CODE (ttr) != OFFSET_TYPE) return 1; else if (TREE_CODE (ttr) == VOID_TYPE && TREE_CODE (ttl) != FUNCTION_TYPE && TREE_CODE (ttl) != METHOD_TYPE && TREE_CODE (ttl) != OFFSET_TYPE) return -1; else if (TREE_CODE (ttl) == POINTER_TYPE || TREE_CODE (ttl) == ARRAY_TYPE) { if (comp_ptr_ttypes (ttl, ttr)) return 1; else if (comp_ptr_ttypes (ttr, ttl)) return -1; return 0; } } /* Const and volatile mean something different for function types, so the usual checks are not appropriate. */ if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE) return comp_target_types (ttl, ttr, nptrs - 1); /* Make sure that the cv-quals change only in the same direction as the target type. */ { int t; int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr); int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr); if ((c > 0 && v < 0) || (c < 0 && v > 0)) return 0; if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr)) return (c + v < 0) ? -1 : 1; t = comp_target_types (ttl, ttr, nptrs - 1); if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0)) return t; return 0; } } if (TREE_CODE (ttr) == REFERENCE_TYPE) return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs); if (TREE_CODE (ttr) == ARRAY_TYPE) return comp_array_types (comp_target_types, ttl, ttr, 0); else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE) if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs)) switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1)) { case 0: return 0; case 1: return 1; case 2: return -1; default: my_friendly_abort (112); } else return 0; /* for C++ */ else if (TREE_CODE (ttr) == OFFSET_TYPE) { /* Contravariance: we can assign a pointer to base member to a pointer to derived member. Note difference from simple pointer case, where we can pass a pointer to derived to a pointer to base. */ if (comptypes (TYPE_OFFSET_BASETYPE (ttr), TYPE_OFFSET_BASETYPE (ttl), 0)) return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs); else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0) && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs)) return -1; } else if (IS_AGGR_TYPE (ttl)) { if (nptrs < 0) return 0; if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0)) return 1; if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0)) return -1; return 0; } return 0;}/* If two types share a common base type, return that basetype. If there is not a unique most-derived base type, this function returns ERROR_MARK_NODE. */treecommon_base_type (tt1, tt2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -