aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-typeck.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r--gcc/c-typeck.c118
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);
+}