diff options
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r-- | gcc/c-typeck.c | 118 |
1 files changed, 85 insertions, 33 deletions
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d5046d5f425..9ddafe10c5d 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1352,40 +1352,17 @@ default_function_array_conversion (tree 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. - In addition, manifest constants symbols are replaced by their values. */ + +/* EXP is an expression of integer type. Apply the integer promotions + to it and return the promoted value. */ tree -default_conversion (tree exp) +perform_integral_promotions (tree exp) { - tree orig_exp; tree type = TREE_TYPE (exp); enum tree_code code = TREE_CODE (type); - if (code == FUNCTION_TYPE || code == ARRAY_TYPE) - return default_function_array_conversion (exp); - - /* Constants can be used directly unless they're not loadable. */ - if (TREE_CODE (exp) == CONST_DECL) - exp = DECL_INITIAL (exp); - - /* Replace a nonvolatile const static variable with its value unless - it is an array, in which case we must be sure that taking the - address of the array produces consistent results. */ - else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) - { - exp = decl_constant_value_for_broken_optimization (exp); - type = TREE_TYPE (exp); - } - - /* Strip no-op conversions. */ - orig_exp = exp; - STRIP_TYPE_NOPS (exp); - - if (TREE_NO_WARNING (orig_exp)) - TREE_NO_WARNING (exp) = 1; + gcc_assert (INTEGRAL_TYPE_P (type)); /* Normally convert enums to int, but convert wide enums to something wider. */ @@ -1400,6 +1377,8 @@ default_conversion (tree exp) 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 @@ -1418,6 +1397,48 @@ default_conversion (tree 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. + In addition, manifest constants symbols are replaced by their values. */ + +tree +default_conversion (tree exp) +{ + tree orig_exp; + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + + if (code == FUNCTION_TYPE || code == ARRAY_TYPE) + return default_function_array_conversion (exp); + + /* Constants can be used directly unless they're not loadable. */ + if (TREE_CODE (exp) == CONST_DECL) + exp = DECL_INITIAL (exp); + + /* Replace a nonvolatile const static variable with its value unless + it is an array, in which case we must be sure that taking the + address of the array produces consistent results. */ + else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) + { + exp = decl_constant_value_for_broken_optimization (exp); + type = TREE_TYPE (exp); + } + + /* Strip no-op conversions. */ + orig_exp = exp; + STRIP_TYPE_NOPS (exp); + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; + + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); + if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); @@ -2540,6 +2561,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) break; case TRUTH_NOT_EXPR: + /* ??? Why do most validation here but that for non-lvalue arrays + in c_objc_common_truthvalue_conversion? */ if (typecode != INTEGER_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE @@ -2549,7 +2572,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) error ("wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = lang_hooks.truthvalue_conversion (arg); + arg = c_objc_common_truthvalue_conversion (arg); return invert_truthvalue (arg); case NOP_EXPR: @@ -2905,8 +2928,6 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) tree result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; - ifexp = lang_hooks.truthvalue_conversion (default_conversion (ifexp)); - /* Promote both alternatives. */ if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) @@ -7295,8 +7316,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, but that does not mean the operands should be converted to ints! */ result_type = integer_type_node; - op0 = lang_hooks.truthvalue_conversion (op0); - op1 = lang_hooks.truthvalue_conversion (op1); + op0 = c_common_truthvalue_conversion (op0); + op1 = c_common_truthvalue_conversion (op1); converted = 1; } break; @@ -7776,3 +7797,34 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return result; } } + + +/* Convert EXPR to be a truth-value, validating its type for this + purpose. Passes EXPR to default_function_array_conversion. */ + +tree +c_objc_common_truthvalue_conversion (tree expr) +{ + expr = default_function_array_conversion (expr); + switch (TREE_CODE (TREE_TYPE (expr))) + { + case ARRAY_TYPE: + error ("used array that cannot be converted to pointer where scalar is required"); + return error_mark_node; + + case RECORD_TYPE: + error ("used struct type value where scalar is required"); + return error_mark_node; + + case UNION_TYPE: + error ("used union type value where scalar is required"); + return error_mark_node; + + default: + break; + } + + /* ??? Should we also give an error for void and vectors rather than + leaving those to give errors later? */ + return c_common_truthvalue_conversion (expr); +} |