diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fcac50b2ae7..8bd9d404a78 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2005-03-23 Joseph S. Myers + + * c-common.h (default_conversion): Remove. + (perform_integral_promotions): Add. + * c-tree.h (default_conversion): Add. + * c-typeck.c (perform_integral_promotions): New, split out from + default_conversion. + * c-common.c (check_case_value): Use perform_integral_promotions, + not default_conversion. + (c_add_case_label): Don't continue processing case label after + found to be pointer. + 2005-03-23 Mark Mitchell * gcc.c (do_spec_1): Do not add a -L path for a directory in diff --git a/gcc/c-common.c b/gcc/c-common.c index a18520d9e0d..d4b9d5cda8e 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1427,15 +1427,14 @@ check_case_value (tree value) value = fold (value); } - if (TREE_CODE (value) != INTEGER_CST - && value != error_mark_node) + if (TREE_CODE (value) == INTEGER_CST) + /* Promote char or short to int. */ + value = perform_integral_promotions (value); + else if (value != error_mark_node) { error ("case label does not reduce to an integer constant"); value = error_mark_node; } - else - /* Promote char or short to int. */ - value = default_conversion (value); constant_expression_warning (value); @@ -3514,7 +3513,10 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type, && POINTER_TYPE_P (TREE_TYPE (low_value))) || (high_value && TREE_TYPE (high_value) && POINTER_TYPE_P (TREE_TYPE (high_value)))) - error ("pointers are not permitted as case values"); + { + error ("pointers are not permitted as case values"); + goto error_out; + } /* Case ranges are a GNU extension. */ if (high_value && pedantic) diff --git a/gcc/c-common.h b/gcc/c-common.h index 64daf34b440..63dcb10b40c 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -808,7 +808,7 @@ extern tree build_break_stmt (void); extern tree build_unary_op (enum tree_code, tree, int); extern tree build_binary_op (enum tree_code, tree, tree, int); -extern tree default_conversion (tree); +extern tree perform_integral_promotions (tree); /* Given two integer or real types, return the type for their sum. Given two compatible ANSI C types, returns the merged type. */ diff --git a/gcc/c-tree.h b/gcc/c-tree.h index adace275c38..bbfed6abbaf 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -460,6 +460,7 @@ extern int comptypes (tree, tree); extern bool c_mark_addressable (tree); extern void c_incomplete_type_error (tree, tree); extern tree c_type_promotes_to (tree); +extern tree default_conversion (tree); extern tree composite_type (tree, tree); extern tree build_component_ref (tree, tree); extern tree build_indirect_ref (tree, const char *); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d5046d5f425..a89c87a3601 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1352,6 +1352,55 @@ default_function_array_conversion (tree exp) return exp; } + +/* EXP is an expression of integer type. Apply the integer promotions + to it and return the promoted value. */ + +tree +perform_integral_promotions (tree exp) +{ + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + + gcc_assert (INTEGRAL_TYPE_P (type)); + + /* Normally convert enums to int, + but convert wide enums to something wider. */ + if (code == ENUMERAL_TYPE) + { + type = c_common_type_for_size (MAX (TYPE_PRECISION (type), + TYPE_PRECISION (integer_type_node)), + ((TYPE_PRECISION (type) + >= TYPE_PRECISION (integer_type_node)) + && TYPE_UNSIGNED (type))); + + return convert (type, exp); + } + + /* ??? This should no longer be needed now bit-fields have their + proper types. */ + if (TREE_CODE (exp) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) + /* If it's thinner than an int, promote it like a + c_promoting_integer_type_p, otherwise leave it alone. */ + && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), + TYPE_PRECISION (integer_type_node))) + return convert (integer_type_node, exp); + + if (c_promoting_integer_type_p (type)) + { + /* Preserve unsignedness if not really getting any wider. */ + if (TYPE_UNSIGNED (type) + && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) + return convert (unsigned_type_node, exp); + + return convert (integer_type_node, exp); + } + + return exp; +} + + /* Perform default promotions for C data used in expressions. Arrays and functions are converted to pointers; enumeral types or short or char, to int. @@ -1387,36 +1436,8 @@ default_conversion (tree exp) if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - /* Normally convert enums to int, - but convert wide enums to something wider. */ - if (code == ENUMERAL_TYPE) - { - type = c_common_type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - ((TYPE_PRECISION (type) - >= TYPE_PRECISION (integer_type_node)) - && TYPE_UNSIGNED (type))); - - return convert (type, exp); - } - - if (TREE_CODE (exp) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) - /* If it's thinner than an int, promote it like a - c_promoting_integer_type_p, otherwise leave it alone. */ - && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), - TYPE_PRECISION (integer_type_node))) - return convert (integer_type_node, exp); - - if (c_promoting_integer_type_p (type)) - { - /* Preserve unsignedness if not really getting any wider. */ - if (TYPE_UNSIGNED (type) - && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) - return convert (unsigned_type_node, exp); - - return convert (integer_type_node, exp); - } + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); if (code == VOID_TYPE) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 237fe33a018..c242a87dd34 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2005-03-23 Joseph S. Myers + + * cp-tree.h (perform_integral_promotions): Remove. + (default_conversion): Add. + 2005-03-22 Mark Mitchell * parser.c (cp_parser_warn_min_max): New function. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e76e216a065..22e9ee0f8a0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4283,7 +4283,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool); #define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false) extern tree inline_conversion (tree); extern tree decay_conversion (tree); -extern tree perform_integral_promotions (tree); +extern tree default_conversion (tree); extern tree build_class_member_access_expr (tree, tree, tree, bool); extern tree finish_class_member_access_expr (tree, tree); extern tree build_x_indirect_ref (tree, const char *);