📄 actions.c
字号:
if (TREE_OPERAND (label, 1) == NULL_TREE) else_range = NULL_TREE; /* (*) -- matches everything */ } else else_range = update_else_range_for_range ( else_range, TREE_OPERAND (label, 0), TREE_OPERAND (label, 1)); return else_range;}static treeupdate_else_range_for_type (else_range, label) tree else_range, label;{ tree type = TREE_TYPE (label); else_range = update_else_range_for_range ( else_range, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type)); return else_range;}static treecompute_else_range (selector, alternatives, selector_no) tree selector, alternatives; int selector_no;{ /* Start with an else-range that spans the entire range of the selector type. */ tree type = TREE_TYPE (TREE_VALUE (selector)); tree range = tree_cons (TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type), NULL_TREE); /* Now remove the values represented by each case lebel specified for that selector. The remaining range is the else-range. */ for ( ; alternatives != NULL_TREE; alternatives = TREE_CHAIN (alternatives)) { tree label; tree label_list = TREE_PURPOSE (alternatives); int this_selector; for (this_selector = 0; this_selector < selector_no ; ++this_selector) label_list = TREE_CHAIN (label_list); for (label = TREE_VALUE (label_list); label != NULL_TREE; label = TREE_CHAIN (label)) { tree label_value = TREE_VALUE (label); if (TREE_CODE (label_value) == INTEGER_CST) range = update_else_range_for_int_const (range, label_value); else if (TREE_CODE (label_value) == RANGE_EXPR) range = update_else_range_for_range_expr (range, label_value); else if (TREE_CODE (label_value) == TYPE_DECL) range = update_else_range_for_type (range, label_value); if (range == NULL_TREE) break; } } return range;}voidcompute_else_ranges (selectors, alternatives) tree selectors, alternatives;{ tree selector; int selector_no = 0; for (selector = selectors; selector != NULL_TREE; selector = TREE_CHAIN (selector)) { if (ELSE_LABEL_SPECIFIED (selector)) TREE_PURPOSE (selector) = compute_else_range (selector, alternatives, selector_no); selector_no++; }}static treecheck_case_value (label_value, selector) tree label_value, selector;{ if (TREE_CODE (label_value) == ERROR_MARK) return label_value; if (TREE_CODE (selector) == ERROR_MARK) return selector; /* Z.200 (6.4 Case action) says: "The class of any discrete expression in the case selector list must be compatible with the corresponding (by position) class of the resulting list of classes of the case label list occurrences ...". We don't actually construct the resulting list of classes, but this test should be more-or-less equivalent. I think... */ if (!CH_COMPATIBLE_CLASSES (selector, label_value)) { error ("case selector not compatible with label"); return error_mark_node; } /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ STRIP_TYPE_NOPS (label_value); if (TREE_CODE (label_value) != INTEGER_CST) { error ("case label does not reduce to an integer constant"); return error_mark_node; } constant_expression_warning (label_value); return label_value;}voidchill_handle_case_default (){ tree duplicate; register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); int success = pushcase (NULL_TREE, 0, label, &duplicate); if (success == 1) error ("ELSE label not within a CASE statement");#if 0 else if (success == 2) { error ("multiple default labels found in a CASE statement"); error_with_decl (duplicate, "this is the first ELSE label"); }#endif}/* Handle cases label such as (I:J): or (modename): */static voidchill_handle_case_label_range (min_value, max_value, selector) tree min_value, max_value, selector;{ register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); min_value = check_case_value (min_value, selector); max_value = check_case_value (max_value, selector); if (TREE_CODE (min_value) != ERROR_MARK && TREE_CODE (max_value) != ERROR_MARK) { tree duplicate; int success = pushcase_range (min_value, max_value, convert, label, &duplicate); if (success == 1) error ("label found outside of CASE statement"); else if (success == 2) { error ("duplicate CASE value"); error_with_decl (duplicate, "this is the first entry for that value"); } else if (success == 3) error ("CASE value out of range"); else if (success == 4) error ("empty range"); else if (success == 5) error ("label within scope of cleanup or variable array"); }}voidchill_handle_case_label (label_value, selector) tree label_value, selector;{ if (label_value == NULL_TREE || TREE_CODE (label_value) == ERROR_MARK) return; if (TREE_CODE (label_value) == RANGE_EXPR) { if (TREE_OPERAND (label_value, 0) == NULL_TREE) chill_handle_case_default (); /* i.e. (ELSE): or (*): */ else chill_handle_case_label_range (TREE_OPERAND (label_value, 0), TREE_OPERAND (label_value, 1), selector); } else if (TREE_CODE (label_value) == TYPE_DECL) { tree type = TREE_TYPE (label_value); if (! discrete_type_p (type)) error ("mode in label is not discrete"); else chill_handle_case_label_range (TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type), selector); } else { register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); label_value = check_case_value (label_value, selector); if (TREE_CODE (label_value) != ERROR_MARK) { tree duplicate; int success = pushcase (label_value, convert, label, &duplicate); if (success == 1) error ("label not within a CASE statement"); else if (success == 2) { error ("duplicate case value"); error_with_decl (duplicate, "this is the first entry for that value"); } else if (success == 3) error ("CASE value out of range"); else if (success == 4) error ("empty range"); else if (success == 5) error ("label within scope of cleanup or variable array"); } }}intchill_handle_single_dimension_case_label ( selector, label_spec, expand_exit_needed, caseaction_flag) tree selector, label_spec; int *expand_exit_needed, *caseaction_flag;{ tree labels, one_label; int no_completeness_check = 0; if (*expand_exit_needed || *caseaction_flag == 1) { expand_exit_something (); *expand_exit_needed = 0; } for (labels = label_spec; labels != NULL_TREE; labels = TREE_CHAIN (labels)) for (one_label = TREE_VALUE (labels); one_label != NULL_TREE; one_label = TREE_CHAIN (one_label)) { if (TREE_VALUE (one_label) == case_else_node) no_completeness_check = 1; chill_handle_case_label (TREE_VALUE (one_label), selector); } *caseaction_flag = 1; return no_completeness_check;}static treechill_handle_multi_case_label_range (low, high, selector) tree low, high, selector;{ tree low_expr, high_expr, and_expr; tree selector_type; int low_target_val, high_target_val; int low_type_val, high_type_val; /* we can eliminate some tests is the low and/or high value in the given range are outside the range of the selector type. */ low_target_val = TREE_INT_CST_LOW (low); high_target_val = TREE_INT_CST_LOW (high); selector_type = TREE_TYPE (selector); low_type_val = TREE_INT_CST_LOW (TYPE_MIN_VALUE (selector_type)); high_type_val = TREE_INT_CST_LOW (TYPE_MAX_VALUE (selector_type)); if (low_target_val > high_type_val || high_target_val < low_type_val) return boolean_false_node; /* selector never in range */ if (low_type_val >= low_target_val) { if (high_type_val <= high_target_val) return boolean_true_node; /* always in the range */ return build_compare_expr (LE_EXPR, selector, high); } if (high_type_val <= high_target_val) return build_compare_expr (GE_EXPR, selector, low); /* The target range in completely within the range of the selector, but we might be able to save a test if the upper bound is the same as the lower bound. */ if (low_target_val == high_target_val) return build_compare_expr (EQ_EXPR, selector, low); /* No optimizations possible. Just generate tests against the upper and lower bound of the target */ low_expr = build_compare_expr (GE_EXPR, selector, low); high_expr = build_compare_expr (LE_EXPR, selector, high); and_expr = build_chill_binary_op (TRUTH_ANDIF_EXPR, low_expr, high_expr); return and_expr;}static treechill_handle_multi_case_else_label (selector) tree selector;{ tree else_range, selector_value, selector_type; tree low, high, larg; else_range = TREE_PURPOSE (selector); if (else_range == NULL_TREE) return boolean_false_node; /* no values in ELSE range */ /* Test each of the ranges in the else-range chain */ selector_value = TREE_VALUE (selector); selector_type = TREE_TYPE (selector_value); low = convert (selector_type, TREE_PURPOSE (else_range)); high = convert (selector_type, TREE_VALUE (else_range)); larg = chill_handle_multi_case_label_range (low, high, selector_value); for (else_range = TREE_CHAIN (else_range); else_range != NULL_TREE; else_range = TREE_CHAIN (else_range)) { tree rarg; low = convert (selector_type, TREE_PURPOSE (else_range)); high = convert (selector_type, TREE_VALUE (else_range)); rarg = chill_handle_multi_case_label_range (low, high, selector_value); larg = build_chill_binary_op (TRUTH_ORIF_EXPR, larg, rarg); } return larg;}static treechill_handle_multi_case_label (selector, label) tree selector, label;{ tree expr = NULL_TREE; if (label == NULL_TREE || TREE_CODE (label) == ERROR_MARK) return NULL_TREE; if (TREE_CODE (label) == INTEGER_CST) { int target_val = TREE_INT_CST_LOW (label); tree selector_type = TREE_TYPE (TREE_VALUE (selector)); int low_type_val = TREE_INT_CST_LOW (TYPE_MIN_VALUE (selector_type)); int high_type_val = TREE_INT_CST_LOW (TYPE_MAX_VALUE (selector_type)); if (target_val < low_type_val || target_val > high_type_val) expr = boolean_false_node; else expr = build_compare_expr (EQ_EXPR, TREE_VALUE (selector), label); } else if (TREE_CODE (label) == RANGE_EXPR) { if (TREE_OPERAND (label, 0) == NULL_TREE) { if (TREE_OPERAND (label, 1) == NULL_TREE) expr = boolean_true_node; /* (*) -- matches everything */ else expr = chill_handle_multi_case_else_label (selector); } else { tree low = TREE_OPERAND (label, 0); tree high = TREE_OPERAND (label, 1); if (TREE_CODE (low) != INTEGER_CST) { error ("Lower bound of range must be a discrete literal expression"); expr = error_mark_node; } if (TREE_CODE (high) != INTEGER_CST) { error ("Upper bound of range must be a discrete literal expression"); expr = error_mark_node; } if (expr != error_mark_node) { expr = chill_handle_multi_case_label_range ( low, high, TREE_VALUE (selector)); } } } else if (TREE_CODE (label) == TYPE_DECL) { tree type = TREE_TYPE (label); if (! discrete_type_p (type)) { error ("mode in label is not discrete"); expr = error_mark_node; } else expr = chill_handle_multi_case_label_range ( TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type), TREE_VALUE (selector)); } else { error ("The CASE label is not valid"); expr = error_mark_node; } return expr;}static treechill_handle_multi_case_label_list (selector, labels) tree selector, labels;{ tree one_label, larg, rarg; one_label = TREE_VALUE (labels); larg = chill_handle_multi_case_label (selector, TREE_VALUE (one_label)); for (one_label = TREE_CHAIN (one_label); one_label != NULL_TREE; one_label = TREE_CHAIN (one_label)) { rarg = chill_handle_multi_case_label (selector, TREE_VALUE (one_label)); larg = build_chill_binary_op (TRUTH_ORIF_EXPR, larg, rarg); } return larg;}treebuild_multi_case_selector_expression (selector_list, label_spec) tree selector_list, label_spec;{ tree labels, selector, larg, rarg; labels = label_spec; selector = selector_list; larg = chill_handle_multi_case_label_list(selector, labels); for (labels = TREE_CHAIN (labels), selector = TREE_CHAIN (selector); labels != NULL_TREE && selector != NULL_TREE; labels = TREE_CHAIN (labels), selector = TREE_CHAIN (selector)) { rarg = chill_handle_multi_case_label_list(selector, labels); larg = build_chill_binary_op (TRUTH_ANDIF_EXPR, larg, rarg); } if (labels != NULL_TREE || selector != NULL_TREE) error ("The number of CASE selectors does not match the number of CASE label lists"); return larg;}#define BITARRAY_TEST(ARRAY, INDEX) \ ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\ & (1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR)))#define BITARRAY_SET(ARRAY, INDEX) \ ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\ |= 1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR))/* CASES_SEEN is a set (bitarray) of length COUNT. For each element that is zero, print an error message, assume the element have the given TYPE. */static voidprint_missing_cases (type, cases_seen, count) tree type; unsigned char *cases_seen; long count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -