📄 typeck.c
字号:
if (list_length (a1) < list_length (a2)) attributes = a2, a2 = a1; for (; a2; a2 = TREE_CHAIN (a2)) if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)), attributes) == NULL_TREE) { a1 = copy_node (a2); TREE_CHAIN (a1) = attributes; attributes = a1; } } } } /* 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 (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); /* If one type is complex, form the common type of the non-complex components, then make that complex. Use T1 or T2 if it is the required type. */ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) { tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; tree subtype = common_type (subtype1, subtype2); if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) return build_type_attribute_variant (t1, attributes); else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) return build_type_attribute_variant (t2, attributes); else return build_type_attribute_variant (build_complex_type (subtype), attributes); } switch (code1) { case INTEGER_TYPE: case REAL_TYPE: /* If only one is real, use it as the result. */ if (code1 == REAL_TYPE && code2 != REAL_TYPE) return build_type_attribute_variant (t1, attributes); if (code2 == REAL_TYPE && code1 != REAL_TYPE) return build_type_attribute_variant (t2, attributes); /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) return build_type_attribute_variant (t1, attributes); else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) return build_type_attribute_variant (t2, attributes); /* Same precision. Prefer longs to ints even when same size. */ if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) return build_type_attribute_variant (long_unsigned_type_node, attributes); if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) { /* But preserve unsignedness from the other type, since long cannot hold all the values of an unsigned int. */ if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2)) t1 = long_unsigned_type_node; else t1 = long_integer_type_node; return build_type_attribute_variant (t1, attributes); } if (TYPE_MAIN_VARIANT (t1) == long_double_type_node || TYPE_MAIN_VARIANT (t2) == long_double_type_node) return build_type_attribute_variant (long_double_type_node, attributes); /* Otherwise prefer the unsigned one. */ if (TREE_UNSIGNED (t1)) return build_type_attribute_variant (t1, attributes); else return build_type_attribute_variant (t2, attributes); case POINTER_TYPE: case REFERENCE_TYPE: /* For two pointers, do this recursively on the target type, and combine the qualifiers of the two types' targets. */ /* This code was turned off; I don't know why. But ANSI C++ specifies doing this with the qualifiers. So I turned it on again. */ { tree tt1 = TREE_TYPE (t1); tree tt2 = TREE_TYPE (t2); tree b1, b2; int type_quals; tree target; if (TREE_CODE (tt1) == OFFSET_TYPE) { b1 = TYPE_OFFSET_BASETYPE (tt1); b2 = TYPE_OFFSET_BASETYPE (tt2); tt1 = TREE_TYPE (tt1); tt2 = TREE_TYPE (tt2); } else b1 = b2 = NULL_TREE; type_quals = (CP_TYPE_QUALS (tt1) | CP_TYPE_QUALS (tt2)); tt1 = TYPE_MAIN_VARIANT (tt1); tt2 = TYPE_MAIN_VARIANT (tt2); if (tt1 == tt2) target = tt1; else if (b1) { compiler_error ("common_type called with uncommon member types"); target = tt1; } else if (tt1 == void_type_node || tt2 == void_type_node) target = void_type_node; else if (tt1 == unknown_type_node) target = tt2; else if (tt2 == unknown_type_node) target = tt1; else target = common_type (tt1, tt2); target = cp_build_qualified_type (target, type_quals); if (b1) { if (same_type_p (b1, b2) || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))) target = build_offset_type (b2, target); else if (binfo_or_else (b2, b1)) target = build_offset_type (b1, target); } if (code1 == POINTER_TYPE) t1 = build_pointer_type (target); else t1 = build_reference_type (target); t1 = build_type_attribute_variant (t1, attributes); if (TREE_CODE (target) == METHOD_TYPE) t1 = build_ptrmemfunc_type (t1); return t1; } case ARRAY_TYPE: { tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) return build_type_attribute_variant (t1, attributes); if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) return build_type_attribute_variant (t2, attributes); /* Merge the element types, and have a size if either arg has one. */ t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); return build_type_attribute_variant (t1, attributes); } case FUNCTION_TYPE: /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); tree rval, raises; /* Save space: see if the result is identical to one of the args. */ if (valtype == TREE_TYPE (t1) && ! p2) return build_type_attribute_variant (t1, attributes); if (valtype == TREE_TYPE (t2) && ! p1) return build_type_attribute_variant (t2, attributes); /* Simple way if one arg fails to specify argument types. */ if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node) { rval = build_function_type (valtype, p2); if ((raises = TYPE_RAISES_EXCEPTIONS (t2))) rval = build_exception_variant (rval, raises); return build_type_attribute_variant (rval, attributes); } raises = TYPE_RAISES_EXCEPTIONS (t1); if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node) { 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: t1 = TYPE_MAIN_VARIANT (t1); t2 = TYPE_MAIN_VARIANT (t2); 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"); return error_mark_node; } 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 (same_type_p (b1, b2) || (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: /* Pointers to members should now be handled by the POINTER_TYPE case above. */ my_friendly_abort (990325); default: return build_type_attribute_variant (t1, attributes); }}/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */intcompexcepttypes (t1, t2) tree t1, t2;{ return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);}/* Compare the array types T1 and T2, using CMP as the type comparison function for the element types. STRICT is as for comptypes. */static intcomp_array_types (cmp, t1, t2, strict) register int (*cmp) PROTO((tree, tree, int)); tree t1, t2; int strict;{ tree d1; tree d2; if (t1 == t2) return 1; /* The type of the array elements must be the same. */ if (!(TREE_TYPE (t1) == TREE_TYPE (t2) || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict & ~COMPARE_REDECLARATION))) return 0; d1 = TYPE_DOMAIN (t1); d2 = TYPE_DOMAIN (t2); if (d1 == d2) return 1; /* If one of the arrays is dimensionless, and the other has a dimension, they are of different types. However, it is legal to write: extern int a[]; int a[3]; by [basic.link]: declarations for an array object can specify array types that differ by the presence or absence of a major array bound (_dcl.array_). */ if (!d1 || !d2) return strict & COMPARE_REDECLARATION; /* Check that the dimensions are the same. */ return (cp_tree_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) && cp_tree_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)));}/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. STRICT is a bitwise-or of the COMPARE_* flags. */intcomptypes (type1, type2, strict) tree type1, type2; int strict;{ register tree t1 = type1; register tree t2 = type2; int attrval, val; int orig_strict = strict; /* The special exemption for redeclaring array types without an array bound only applies at the top level: extern int (*i)[]; int (*i)[8]; is not legal, for example. */ strict &= ~COMPARE_REDECLARATION; /* 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 & COMPARE_RELAXED) { /* 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; } if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); /* Different classes of types can't be compatible. */ if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; /* Qualifiers must match. */ if (CP_TYPE_QUALS (t1) != CP_TYPE_QUALS (t2)) return 0; if (strict == COMPARE_STRICT && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (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 qualifiers (just above). */ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; /* ??? COMP_TYPE_ATTRIBUTES is currently useless for variables as each attribute is its own main variant (`val' will remain 0). */#ifndef COMP_TYPE_ATTRIBUTES#define COMP_TYPE_ATTRIBUTES(t1,t2) 1#endif if (strict & COMPARE_NO_ATTRIBUTES) attrval = 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ else if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2))) return 0; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ val = 0; switch (TREE_CODE (t1)) { case TEMPLATE_TEMPLATE_PARM: if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)) return 0; if (! comp_template_parms (DECL_TEMPLATE_PARMS (TYPE_NAME (t1)), DECL_TEMPLATE_PARMS (TYPE_NAME (t2)))) return 0; if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t1) && ! TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)) return 1; /* Don't check inheritance. */ strict = COMPARE_STRICT; /* fall through */ case RECORD_TYPE: case UNION_TYPE: if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2) && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2) || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)) val = comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2)); look_hard: if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2)) { val = 1; break; } if ((strict & COMPARE_RELAXED) && DERIVED_FROM_P (t2, t1)) { val = 1; break; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -