aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog11
-rw-r--r--gcc/c/c-decl.c48
-rw-r--r--gcc/c/c-typeck.c66
3 files changed, 91 insertions, 34 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 991d0d3..6fea3a9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,14 @@
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-decl.c (finish_struct): If the structure has reverse storage
+ order, rewrite the type of array fields with scalar component. Call
+ maybe_apply_pragma_scalar_storage_order on entry.
+ * c-typeck.c (build_unary_op) <ADDR_EXPR>: Remove left-overs. Issue
+ errors on bit-fields and reverse SSO here and not...
+ (c_mark_addressable): ...here.
+ (output_init_element): Adjust call to initializer_constant_valid_p.
+ (c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER.
+
2015-11-06 David Malcolm <dmalcolm@redhat.com>
* c-decl.c (warn_defaults_to): Update for change in signature
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e9bdceb..a3d8ead 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -7724,6 +7724,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
TYPE_FIELDS (t) = fieldlist;
+ maybe_apply_pragma_scalar_storage_order (t);
+
layout_type (t);
if (TYPE_SIZE_UNIT (t)
@@ -7732,27 +7734,45 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
&& !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
error ("type %qT is too large", t);
- /* Give bit-fields their proper types. */
- {
- tree *fieldlistp = &fieldlist;
- while (*fieldlistp)
- if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
- && TREE_TYPE (*fieldlistp) != error_mark_node)
+ /* Give bit-fields their proper types and rewrite the type of array fields
+ with scalar component if the enclosing type has reverse storage order. */
+ for (tree field = fieldlist; field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL
+ && DECL_INITIAL (field)
+ && TREE_TYPE (field) != error_mark_node)
{
unsigned HOST_WIDE_INT width
- = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
- tree type = TREE_TYPE (*fieldlistp);
+ = tree_to_uhwi (DECL_INITIAL (field));
+ tree type = TREE_TYPE (field);
if (width != TYPE_PRECISION (type))
{
- TREE_TYPE (*fieldlistp)
+ TREE_TYPE (field)
= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
- DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+ DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
}
- DECL_INITIAL (*fieldlistp) = 0;
+ DECL_INITIAL (field) = 0;
}
- else
- fieldlistp = &DECL_CHAIN (*fieldlistp);
- }
+ else if (TYPE_REVERSE_STORAGE_ORDER (t)
+ && TREE_CODE (field) == FIELD_DECL
+ && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
+ {
+ tree ftype = TREE_TYPE (field);
+ tree ctype = strip_array_types (ftype);
+ if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode)
+ {
+ tree fmain_type = TYPE_MAIN_VARIANT (ftype);
+ tree *typep = &fmain_type;
+ do {
+ *typep = build_distinct_type_copy (*typep);
+ TYPE_REVERSE_STORAGE_ORDER (*typep) = 1;
+ typep = &TREE_TYPE (*typep);
+ } while (TREE_CODE (*typep) == ARRAY_TYPE);
+ TREE_TYPE (field)
+ = c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
+ }
+ }
+ }
/* Now we have the truly final field list.
Store it in this type and in the variants. */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 33f5ead..2080db9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4169,18 +4169,10 @@ build_unary_op (location_t location,
goto return_build_unary_op;
}
- /* For &x[y], return x+y */
- if (TREE_CODE (arg) == ARRAY_REF)
- {
- tree op0 = TREE_OPERAND (arg, 0);
- if (!c_mark_addressable (op0))
- return error_mark_node;
- }
-
/* Anything not already handled and not a true memory reference
or a non-lvalue array is an error. */
- else if (typecode != FUNCTION_TYPE && !flag
- && !lvalue_or_else (location, arg, lv_addressof))
+ if (typecode != FUNCTION_TYPE && !flag
+ && !lvalue_or_else (location, arg, lv_addressof))
return error_mark_node;
/* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -4218,6 +4210,39 @@ build_unary_op (location_t location,
argtype = c_build_qualified_type (argtype, quals);
}
+ switch (TREE_CODE (arg))
+ {
+ case COMPONENT_REF:
+ if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ error ("cannot take address of bit-field %qD",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
+
+ /* ... fall through ... */
+
+ case ARRAY_REF:
+ if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
+ {
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
+ && !VECTOR_TYPE_P (TREE_TYPE (arg)))
+ {
+ error ("cannot take address of scalar with reverse storage "
+ "order");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
+ warning (OPT_Wscalar_storage_order, "address of array with "
+ "reverse scalar storage order requested");
+ }
+
+ default:
+ break;
+ }
+
if (!c_mark_addressable (arg))
return error_mark_node;
@@ -4360,15 +4385,6 @@ c_mark_addressable (tree exp)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
- if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
- {
- error
- ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
- return false;
- }
-
- /* ... fall through ... */
-
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
@@ -8444,7 +8460,11 @@ output_init_element (location_t loc, tree value, tree origtype,
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
- else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
+ else if (!initializer_constant_valid_p (value,
+ TREE_TYPE (value),
+ AGGREGATE_TYPE_P (constructor_type)
+ && TYPE_REVERSE_STORAGE_ORDER
+ (constructor_type))
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& DECL_C_BIT_FIELD (field)
@@ -13238,6 +13258,12 @@ c_build_qualified_type (tree type, int type_quals)
= build_array_type (TYPE_CANONICAL (element_type),
domain? TYPE_CANONICAL (domain)
: NULL_TREE);
+ if (TYPE_REVERSE_STORAGE_ORDER (type))
+ {
+ unqualified_canon
+ = build_distinct_type_copy (unqualified_canon);
+ TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
+ }
TYPE_CANONICAL (t)
= c_build_qualified_type (unqualified_canon, type_quals);
}