📄 typeck.c
字号:
if (CH_DERIVED_FLAG (expr)) { class.kind = CH_DERIVED_CLASS; class.mode = TREE_TYPE (expr); return class; } /* The M-Reference contains <references location> (address-of) expressions. Note that something that's been converted to a reference doesn't count. */ if (TREE_CODE (expr) == ADDR_EXPR && TREE_CODE (TREE_TYPE (expr)) != REFERENCE_TYPE) { class.kind = CH_REFERENCE_CLASS; class.mode = TREE_TYPE (TREE_TYPE (expr)); return class; } /* The M-Value class contains expressions with a known, specific mode M. */ class.kind = CH_VALUE_CLASS; class.mode = TREE_TYPE (expr); return class;}/* Returns >= 1 iff REF is a location. Return 2 if it is referable. */int chill_location (ref) tree ref;{ register enum tree_code code = TREE_CODE (ref); switch (code) { case REALPART_EXPR: case IMAGPART_EXPR: case ARRAY_REF: case PACKED_ARRAY_REF: case COMPONENT_REF: case NOP_EXPR: /* RETYPE_EXPR */ return chill_location (TREE_OPERAND (ref, 0)); case COMPOUND_EXPR: return chill_location (TREE_OPERAND (ref, 1)); case BIT_FIELD_REF: case SLICE_EXPR: /* A bit-string slice is nor referable. */ return chill_location (TREE_OPERAND (ref, 0)) == 0 ? 0 : 1; case CONSTRUCTOR: case STRING_CST: return 0; case INDIRECT_REF: case VAR_DECL: case PARM_DECL: case RESULT_DECL: case ERROR_MARK: if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) return 2; break; default: break; } return 0;}intchill_referable (val) tree val;{ return chill_location (val) > 1;}/* Make a copy of MODE, but with the given NOVELTY. */treecopy_novelty (novelty, mode) tree novelty, mode;{ if (CH_NOVELTY (mode) != novelty) { mode = copy_node (mode); TYPE_MAIN_VARIANT (mode) = mode; TYPE_NEXT_VARIANT (mode) = 0; TYPE_POINTER_TO (mode) = 0; TYPE_REFERENCE_TO (mode) = 0; SET_CH_NOVELTY (mode, novelty); } return mode;}struct mode_chain{ struct mode_chain *prev; tree mode1, mode2;};/* Tests if MODE1 and MODE2 are SIMILAR. This is more or less as defined in the Blue Book, though see FIXME for parts that are unfinished. CHAIN is used to catch infinite recursion: It is a list of pairs of mode arguments to calls to chill_similar "outer" to this call. */ intchill_similar (mode1, mode2, chain) tree mode1, mode2; struct mode_chain *chain;{ int varying1, varying2; tree t1, t2; struct mode_chain *link, node; if (mode1 == NULL_TREE || mode2 == NULL_TREE) return 0; while (TREE_CODE (mode1) == REFERENCE_TYPE) mode1 = TREE_TYPE (mode1); while (TREE_CODE (mode2) == REFERENCE_TYPE) mode2 = TREE_TYPE (mode2); /* Range modes are similar to their parent types. */ while (TREE_CODE (mode1) == INTEGER_TYPE && TREE_TYPE (mode1) != NULL_TREE) mode1 = TREE_TYPE (mode1); while (TREE_CODE (mode2) == INTEGER_TYPE && TREE_TYPE (mode2) != NULL_TREE) mode2 = TREE_TYPE (mode2); /* see Z.200 sections 12.1.2.2 and 13.2 - all integer precisions are similar to INT and to each other */ if (mode1 == mode2 || (TREE_CODE (mode1) == INTEGER_TYPE && TREE_CODE (mode2) == INTEGER_TYPE)) return 1; /* This guards against certain kinds of recursion. For example: SYNMODE a = STRUCT ( next REF a ); SYNMODE b = STRUCT ( next REF b ); These moes are similar, but will get an infite recursion trying to prove that. So, if we are recursing, assume the moes are similar. If they are not, we'll find some other discrepancy. */ for (link = chain; link != NULL; link = link->prev) { if (link->mode1 == mode1 && link->mode2 == mode2) return 1; } node.mode1 = mode1; node.mode2 = mode2; node.prev = chain; varying1 = chill_varying_type_p (mode1); varying2 = chill_varying_type_p (mode2); /* FIXME: This isn't quite strict enough. */ if ((varying1 && varying2) || (varying1 && TREE_CODE (mode2) == ARRAY_TYPE) || (varying2 && TREE_CODE (mode1) == ARRAY_TYPE)) return 1; if (TREE_CODE(mode1) != TREE_CODE(mode2)) { if (flag_old_strings) { /* The recursion is to handle varying strings. */ if ((TREE_CODE (mode1) == CHAR_TYPE && CH_SIMILAR (mode2, string_one_type_node)) || (TREE_CODE (mode2) == CHAR_TYPE && CH_SIMILAR (mode1, string_one_type_node))) return 1; if ((TREE_CODE (mode1) == BOOLEAN_TYPE && CH_SIMILAR (mode2, bitstring_one_type_node)) || (TREE_CODE (mode2) == BOOLEAN_TYPE && CH_SIMILAR (mode1, bitstring_one_type_node))) return 1; } if (TREE_CODE (mode1) == FUNCTION_TYPE && TREE_CODE (mode2) == POINTER_TYPE && TREE_CODE (TREE_TYPE (mode2)) == FUNCTION_TYPE) mode2 = TREE_TYPE (mode2); else if (TREE_CODE (mode2) == FUNCTION_TYPE && TREE_CODE (mode1) == POINTER_TYPE && TREE_CODE (TREE_TYPE (mode1)) == FUNCTION_TYPE) mode1 = TREE_TYPE (mode1); else return 0; } if (CH_IS_BUFFER_MODE (mode1) && CH_IS_BUFFER_MODE (mode2)) { tree len1 = max_queue_size (mode1); tree len2 = max_queue_size (mode2); return tree_int_cst_equal (len1, len2); } else if (CH_IS_EVENT_MODE (mode1) && CH_IS_EVENT_MODE (mode2)) { tree len1 = max_queue_size (mode1); tree len2 = max_queue_size (mode2); return tree_int_cst_equal (len1, len2); } else if (CH_IS_ACCESS_MODE (mode1) && CH_IS_ACCESS_MODE (mode2)) { tree index1 = access_indexmode (mode1); tree index2 = access_indexmode (mode2); tree record1 = access_recordmode (mode1); tree record2 = access_recordmode (mode2); if (! chill_read_compatible (index1, index2)) return 0; return chill_read_compatible (record1, record2); } switch ((enum chill_tree_code)TREE_CODE (mode1)) { case INTEGER_TYPE: case BOOLEAN_TYPE: case CHAR_TYPE: return 1; case ENUMERAL_TYPE: if (TYPE_VALUES (mode1) == TYPE_VALUES (mode2)) return 1; else { /* FIXME: This is more strict than z.200, which seems to allow the elements to be reordered, as long as they have the same values. */ tree field1 = TYPE_VALUES (mode1); tree field2 = TYPE_VALUES (mode2); while (field1 != NULL_TREE && field2 != NULL_TREE) { tree value1, value2; /* Check that the names are equal. */ if (TREE_PURPOSE (field1) != TREE_PURPOSE (field2)) break; value1 = TREE_VALUE (field1); value2 = TREE_VALUE (field2); /* This isn't quite sufficient in general, but will do ... */ /* Note that proclaim_decl can cause the SET modes to be compared BEFORE they are satisfied, but otherwise chill_similar is mostly called after satisfaction. */ if (TREE_CODE (value1) == CONST_DECL) value1 = DECL_INITIAL (value1); if (TREE_CODE (value2) == CONST_DECL) value2 = DECL_INITIAL (value2); /* Check that the values are equal or both NULL. */ if (!(value1 == NULL_TREE && value2 == NULL_TREE) && (value1 == NULL_TREE || value2 == NULL_TREE || ! tree_int_cst_equal (value1, value2))) break; field1 = TREE_CHAIN (field1); field2 = TREE_CHAIN (field2); } return field1 == NULL_TREE && field2 == NULL_TREE; } case SET_TYPE: /* check for bit strings */ if (CH_BOOLS_TYPE_P (mode1)) return CH_BOOLS_TYPE_P (mode2); if (CH_BOOLS_TYPE_P (mode2)) return CH_BOOLS_TYPE_P (mode1); /* both are powerset modes */ return CH_EQUIVALENT (TYPE_DOMAIN (mode1), TYPE_DOMAIN (mode2)); case POINTER_TYPE: /* Are the referenced modes equivalent? */ return !integer_zerop (chill_equivalent (TREE_TYPE (mode1), TREE_TYPE (mode2), &node)); case ARRAY_TYPE: /* char for char strings */ if (CH_CHARS_TYPE_P (mode1)) return CH_CHARS_TYPE_P (mode2); if (CH_CHARS_TYPE_P (mode2)) return CH_CHARS_TYPE_P (mode1); /* array modes */ if (CH_V_EQUIVALENT (TYPE_DOMAIN (mode1), TYPE_DOMAIN (mode2)) /* Are the elements modes equivalent? */ && !integer_zerop (chill_equivalent (TREE_TYPE (mode1), TREE_TYPE (mode2), &node))) { /* FIXME: Check that element layouts are equivalent */ tree count1 = fold (build (MINUS_EXPR, sizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (mode1)), TYPE_MIN_VALUE (TYPE_DOMAIN (mode1)))); tree count2 = fold (build (MINUS_EXPR, sizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (mode2)), TYPE_MIN_VALUE (TYPE_DOMAIN (mode2)))); tree cond = build_compare_discrete_expr (EQ_EXPR, count1, count2); if (TREE_CODE (cond) == INTEGER_CST) return !integer_zerop (cond); else {#if 0 extern int ignoring; if (!ignoring && range_checking && current_function_decl) return cond;#endif return 1; } } return 0; case RECORD_TYPE: case UNION_TYPE: for (t1 = TYPE_FIELDS (mode1), t2 = TYPE_FIELDS (mode2); t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) { if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; /* Are the field modes equivalent? */ if (integer_zerop (chill_equivalent (TREE_TYPE (t1), TREE_TYPE (t2), &node))) return 0; } return t1 == t2; case FUNCTION_TYPE: if (!chill_l_equivalent (TREE_TYPE (mode1), TREE_TYPE (mode2), &node)) return 0; for (t1 = TYPE_ARG_TYPES (mode1), t2 = TYPE_ARG_TYPES (mode2); t1 != NULL_TREE && t2 != NULL_TREE; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) { tree attr1 = TREE_PURPOSE (t1) ? TREE_PURPOSE (t1) : ridpointers[(int) RID_IN]; tree attr2 = TREE_PURPOSE (t2) ? TREE_PURPOSE (t2) : ridpointers[(int) RID_IN]; if (attr1 != attr2) return 0; if (!chill_l_equivalent (TREE_VALUE (t1), TREE_VALUE (t2), &node)) return 0; } if (t1 != t2) /* Both NULL_TREE */ return 0; /* check list of exception names */ t1 = TYPE_RAISES_EXCEPTIONS (mode1); t2 = TYPE_RAISES_EXCEPTIONS (mode2); if (t1 == NULL_TREE && t2 != NULL_TREE) return 0; if (t1 != NULL_TREE && t2 == NULL_TREE) return 0; if (list_length (t1) != list_length (t2)) return 0; while (t1 != NULL_TREE) { if (value_member (TREE_VALUE (t1), t2) == NULL_TREE) return 0; t1 = TREE_CHAIN (t1); } /* FIXME: Should also check they have the same RECURSIVITY */ return 1; default: ;#if 0 /* Need to handle row modes, instance modes, association modes, access modes, text modes, duration modes, absolute time modes, structure modes, parameterized structure modes */#endif } return 1;}/* Return a node that is true iff MODE1 and MODE2 are equivalent. This is normally boolean_true_node or boolean_false_node, but can be dynamic for dynamic types. CHAIN is as for chill_similar. */treechill_equivalent (mode1, mode2, chain) tree mode1, mode2; struct mode_chain *chain;{ int varying1, varying2; int is_string1, is_string2; tree base_mode1, base_mode2; /* Are the modes v-equivalent? */#if 0 if (!chill_similar (mode1, mode2, chain) || CH_NOVELTY(mode1) != CH_NOVELTY(mode2)) return boolean_false_node;#endif if (!chill_similar (mode1, mode2, chain)) return boolean_false_node; else if (TREE_CODE (mode2) == FUNCTION_TYPE && TREE_CODE (mode1) == POINTER_TYPE && TREE_CODE (TREE_TYPE (mode1)) == FUNCTION_TYPE) /* don't check novelty in this case to avoid error in case of NEWMODE'd proceduremode gets assigned a function */ return boolean_true_node; else if (CH_NOVELTY(mode1) != CH_NOVELTY(mode2)) return boolean_false_node; varying1 = chill_varying_type_p (mode1); varying2 = chill_varying_type_p (mode2); if (varying1 != varying2) return boolean_false_node; base_mode1 = varying1 ? CH_VARYING_ARRAY_TYPE (mode1) : mode1; base_mode2 = varying2 ? CH_VARYING_ARRAY_TYPE (mode2) : mode2; is_string1 = CH_STRING_TYPE_P (base_mode1); is_string2 = CH_STRING_TYPE_P (base_mode2); if (is_string1 || is_string2) { if (is_string1 != is_string2) return boolean_false_node; return fold (build (EQ_EXPR, boolean_type_node, TYPE_SIZE (base_mode1), TYPE_SIZE (base_mode2))); } /* && some more stuff FIXME! */ if (TREE_CODE(mode1) == INTEGER_TYPE || TREE_CODE(mode2) == INTEGER_TYPE) { if (TREE_CODE(mode1) != INTEGER_TYPE || TREE_CODE(mode2) != INTEGER_TYPE) return boolean_false_node; /* If one is a range, the other has to be a range. */ if ((TREE_TYPE (mode1) != NULL_TREE) != (TREE_TYPE (mode2) != NULL_TREE)) return boolean_false_node; if (TYPE_PRECISION (mode1) != TYPE_PRECISION (mode2)) return boolean_false_node; if (!tree_int_cst_equal (TYPE_MIN_VALUE (mode1), TYPE_MIN_VALUE (mode2))) return boolean_false_node; if (!tree_int_cst_equal (TYPE_MAX_VALUE (mode1), TYPE_MAX_VALUE (mode2))) return boolean_false_node; } return boolean_true_node;}static intchill_l_equivalent (mode1, mode2, chain) tree mode1, mode2; struct mode_chain *chain;{ /* Are the modes equivalent? */ if (integer_zerop (chill_equivalent (mode1, mode2, chain))) return 0; if (TYPE_READONLY (mode1) != TYPE_READONLY (mode2))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -