diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 48 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 66 |
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); } |