diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-12-04 22:57:20 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2013-12-04 22:57:20 +0000 |
commit | 296674dbc9842ac009f558390da2bf6e5a9d4409 (patch) | |
tree | 1d857f76a0338447e2abb6b4d8b9d3a69458fff2 | |
parent | 31e071aeb827f49ce2e891620852198e99d44a0c (diff) | |
download | gcc-296674dbc9842ac009f558390da2bf6e5a9d4409.zip gcc-296674dbc9842ac009f558390da2bf6e5a9d4409.tar.gz gcc-296674dbc9842ac009f558390da2bf6e5a9d4409.tar.bz2 |
re PR c/52023 ([C11] _Alignof (double) yields wrong value on x86)
PR c/52023
c-family:
* c-common.c (c_sizeof_or_alignof_type): Add parameter min_alignof
and check field alignment if set.
* c-common.h (c_sizeof_or_alignof_type): Update prototype.
(c_sizeof, c_alignof): Update calls to c_sizeof_or_alignof_type.
c:
* c-parser.c (c_parser_alignas_specifier): Use
c_sizeof_or_alignof_type instead of c_alignof.
(c_parser_alignof_expression): Likewise, with min_alignof
parameter depending on alignof spelling used.
cp:
* typeck.c (cxx_sizeof_or_alignof_type): Update call to
c_sizeof_or_alignof_type.
objc:
* objc-act.c (objc_synthesize_getter): Update calls to
c_sizeof_or_alignof_type.
testsuite:
* gcc.dg/c11-align-6.c: New test.
From-SVN: r205685
-rw-r--r-- | gcc/c-family/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 25 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 6 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 12 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c11-align-6.c | 40 |
11 files changed, 109 insertions, 11 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 35c0003..875b08d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2013-12-04 Joseph Myers <joseph@codesourcery.com> + + PR c/52023 + * c-common.c (c_sizeof_or_alignof_type): Add parameter min_alignof + and check field alignment if set. + * c-common.h (c_sizeof_or_alignof_type): Update prototype. + (c_sizeof, c_alignof): Update calls to c_sizeof_or_alignof_type. + 2013-12-04 Jakub Jelinek <jakub@redhat.com> Marek Polacek <polacek@redhat.com> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index e652802..a06dea8 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -4921,14 +4921,17 @@ c_common_get_alias_set (tree t) } /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where - the second parameter indicates which OPERATOR is being applied. + the IS_SIZEOF parameter indicates which operator is being applied. The COMPLAIN flag controls whether we should diagnose possibly ill-formed constructs or not. LOC is the location of the SIZEOF or - TYPEOF operator. */ + TYPEOF operator. If MIN_ALIGNOF, the least alignment required for + a type in any context should be returned, rather than the normal + alignment for that type. */ tree c_sizeof_or_alignof_type (location_t loc, - tree type, bool is_sizeof, int complain) + tree type, bool is_sizeof, bool min_alignof, + int complain) { const char *op_name; tree value = NULL; @@ -4994,6 +4997,22 @@ c_sizeof_or_alignof_type (location_t loc, value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), size_int (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT)); + else if (min_alignof) + { + unsigned int align = TYPE_ALIGN (type); + align = MIN (align, BIGGEST_ALIGNMENT); +#ifdef BIGGEST_FIELD_ALIGNMENT + align = MIN (align, BIGGEST_FIELD_ALIGNMENT); +#endif + tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, + type); + unsigned int field_align = align; +#ifdef ADJUST_FIELD_ALIGN + field_align = ADJUST_FIELD_ALIGN (field, field_align); +#endif + align = MIN (align, field_align); + value = size_int (align / BITS_PER_UNIT); + } else value = size_int (TYPE_ALIGN_UNIT (type)); } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 664e928..1df9e99 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -759,7 +759,7 @@ extern tree c_wrap_maybe_const (tree, bool); extern tree c_save_expr (tree); extern tree c_common_truthvalue_conversion (location_t, tree); extern void c_apply_type_quals_to_decl (int, tree); -extern tree c_sizeof_or_alignof_type (location_t, tree, bool, int); +extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int); extern tree c_alignof_expr (location_t, tree); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ @@ -792,8 +792,8 @@ extern bool keyword_is_type_qualifier (enum rid); extern bool keyword_is_decl_specifier (enum rid); extern bool cxx_fundamental_alignment_p (unsigned); -#define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, 1) -#define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1) +#define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, false, 1) +#define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, false, 1) /* Subroutine of build_binary_op, used for certain operations. */ extern tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 0603852..4f353e8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,11 @@ +2013-12-04 Joseph Myers <joseph@codesourcery.com> + + PR c/52023 + * c-parser.c (c_parser_alignas_specifier): Use + c_sizeof_or_alignof_type instead of c_alignof. + (c_parser_alignof_expression): Likewise, with min_alignof + parameter depending on alignof spelling used. + 2013-12-04 Marek Polacek <polacek@redhat.com> PR c/54113 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 141c4ce..c78d269 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -3045,7 +3045,8 @@ c_parser_alignas_specifier (c_parser * parser) { struct c_type_name *type = c_parser_type_name (parser); if (type != NULL) - ret = c_alignof (loc, groktypename (type, NULL, NULL)); + ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL), + false, true, 1); } else ret = c_parser_expr_no_commas (parser, NULL).value; @@ -6446,11 +6447,12 @@ c_parser_alignof_expression (c_parser *parser) location_t loc = c_parser_peek_token (parser)->location; tree alignof_spelling = c_parser_peek_token (parser)->value; gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF)); + bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling), + "_Alignof") == 0; /* A diagnostic is not required for the use of this identifier in the implementation namespace; only diagnose it for the C11 spelling because of existing code using the other spellings. */ - if (!flag_isoc11 - && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0) + if (!flag_isoc11 && is_c11_alignof) { if (flag_isoc99) pedwarn (loc, OPT_Wpedantic, "ISO C99 does not support %qE", @@ -6494,7 +6496,9 @@ c_parser_alignof_expression (c_parser *parser) /* alignof ( type-name ). */ c_inhibit_evaluation_warnings--; in_alignof--; - ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL)); + ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name, + NULL, NULL), + false, is_c11_alignof, 1); ret.original_code = ERROR_MARK; ret.original_type = NULL; return ret; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 119f309..2583e5e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2013-12-04 Joseph Myers <joseph@codesourcery.com> + + PR c/52023 + * typeck.c (cxx_sizeof_or_alignof_type): Update call to + c_sizeof_or_alignof_type. + 2013-12-04 Jakub Jelinek <jakub@redhat.com> PR c++/59268 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 9f9f7b6..74fc4d7 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1562,7 +1562,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) } return c_sizeof_or_alignof_type (input_location, complete_type (type), - op == SIZEOF_EXPR, + op == SIZEOF_EXPR, false, complain); } diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 6ec2ef5..366bc3f 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,9 @@ +2013-12-04 Joseph Myers <joseph@codesourcery.com> + + PR c/52023 + * objc-act.c (objc_synthesize_getter): Update calls to + c_sizeof_or_alignof_type. + 2013-11-22 Andrew MacLeod <amacleod@redhat.com> * objc/objc-act.c: Add required include files from gimple.h. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 2a551ee..4a10f57 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -7273,6 +7273,7 @@ objc_synthesize_getter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree pr the same type, there is no need to lookup the ivar. */ size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property), true /* is_sizeof */, + false /* min_alignof */, false /* complain */); if (PROPERTY_NONATOMIC (property)) @@ -7474,6 +7475,7 @@ objc_synthesize_setter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree pr the same type, there is no need to lookup the ivar. */ size_of = c_sizeof_or_alignof_type (location, TREE_TYPE (property), true /* is_sizeof */, + false /* min_alignof */, false /* complain */); if (PROPERTY_NONATOMIC (property)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6703e6a..7779db7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-12-04 Joseph Myers <joseph@codesourcery.com> + + PR c/52023 + * gcc.dg/c11-align-6.c: New test. + 2013-12-04 Marek Polacek <polacek@redhat.com> * c-c++-common/ubsan/overflow-mul-2.c: New test. diff --git a/gcc/testsuite/gcc.dg/c11-align-6.c b/gcc/testsuite/gcc.dg/c11-align-6.c new file mode 100644 index 0000000..7ea994d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-align-6.c @@ -0,0 +1,40 @@ +/* Test C11 _Alignof returning minimum alignment for a type. PR + 52023. */ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +extern void abort (void); +extern void exit (int); + +#define CHECK_ALIGN(TYPE) \ + do \ + { \ + struct { char c; TYPE v; } x; \ + if (_Alignof (TYPE) > __alignof__ (x.v)) \ + abort (); \ + } \ + while (0) + +int +main (void) +{ + CHECK_ALIGN (_Bool); + CHECK_ALIGN (char); + CHECK_ALIGN (signed char); + CHECK_ALIGN (unsigned char); + CHECK_ALIGN (signed short); + CHECK_ALIGN (unsigned short); + CHECK_ALIGN (signed int); + CHECK_ALIGN (unsigned int); + CHECK_ALIGN (signed long); + CHECK_ALIGN (unsigned long); + CHECK_ALIGN (signed long long); + CHECK_ALIGN (unsigned long long); + CHECK_ALIGN (float); + CHECK_ALIGN (double); + CHECK_ALIGN (long double); + CHECK_ALIGN (_Complex float); + CHECK_ALIGN (_Complex double); + CHECK_ALIGN (_Complex long double); + exit (0); +} |