aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-typeck.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index fb5c288..0d639b60 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9956,6 +9956,47 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
goto retry;
}
+/* Expression VALUE coincides with the start of type TYPE in a braced
+ initializer. Return true if we should treat VALUE as initializing
+ the first element of TYPE, false if we should treat it as initializing
+ TYPE as a whole.
+
+ If the initializer is clearly invalid, the question becomes:
+ which choice gives the best error message? */
+
+static bool
+initialize_elementwise_p (tree type, tree value)
+{
+ if (type == error_mark_node || value == error_mark_node)
+ return false;
+
+ gcc_checking_assert (TYPE_MAIN_VARIANT (type) == type);
+
+ tree value_type = TREE_TYPE (value);
+ if (value_type == error_mark_node)
+ return false;
+
+ /* GNU vectors can be initialized elementwise. However, treat any
+ kind of vector value as initializing the vector type as a whole,
+ regardless of whether the value is a GNU vector. Such initializers
+ are valid if and only if they would have been valid in a non-braced
+ initializer like:
+
+ TYPE foo = VALUE;
+
+ so recursing into the vector type would be at best confusing or at
+ worst wrong. For example, when -flax-vector-conversions is in effect,
+ it's possible to initialize a V8HI from a V4SI, even though the vectors
+ have different element types and different numbers of elements. */
+ if (gnu_vector_type_p (type))
+ return !VECTOR_TYPE_P (value_type);
+
+ if (AGGREGATE_TYPE_P (type))
+ return type != TYPE_MAIN_VARIANT (value_type);
+
+ return false;
+}
+
/* Add one non-braced element to the current constructor level.
This adjusts the current position within the constructor's type.
This may also start or terminate implicit levels
@@ -10135,11 +10176,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
- && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE
- || gnu_vector_type_p (fieldtype)))
+ && initialize_elementwise_p (fieldtype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;
@@ -10227,11 +10264,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
- && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE
- || gnu_vector_type_p (fieldtype)))
+ && initialize_elementwise_p (fieldtype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;
@@ -10270,11 +10303,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
else if (value.value != NULL_TREE
- && value.value != error_mark_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
- && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
- || eltcode == UNION_TYPE
- || gnu_vector_type_p (elttype)))
+ && initialize_elementwise_p (elttype, value.value))
{
push_init_level (loc, 1, braced_init_obstack);
continue;