diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-04 22:17:05 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-04 22:17:05 +0000 |
commit | 6b098e91f55238b31ed7eb28741ef1b96d198046 (patch) | |
tree | 0c6d6e6c7c4474708b293d53101ea2650fe22948 | |
parent | 931b245017ca1b7260d2309fd6421428571870e0 (diff) | |
download | gcc-6b098e91f55238b31ed7eb28741ef1b96d198046.tar.gz |
PR c/69669
* c-decl.c (finish_enum): When honoring mode attribute,
make sure to use proper TYPE_MIN_VALUE and TYPE_MAX_VALUE.
* c-c++-common/pr69669.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233154 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr69669.c | 10 |
4 files changed, 40 insertions, 12 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 606b63c7294..931e51d03d8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2016-02-04 Jakub Jelinek <jakub@redhat.com> + + PR c/69669 + * c-decl.c (finish_enum): When honoring mode attribute, + make sure to use proper TYPE_MIN_VALUE and TYPE_MAX_VALUE. + 2016-01-29 Jakub Jelinek <jakub@redhat.com> PR debug/69518 diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index aaccaa88006..5f6f3ee2ad7 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -8037,7 +8037,24 @@ finish_enum (tree enumtype, tree values, tree attributes) precision = MAX (tree_int_cst_min_precision (minnode, sign), tree_int_cst_min_precision (maxnode, sign)); - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) + /* If the precision of the type was specified with an attribute and it + was too small, give an error. Otherwise, use it. */ + if (TYPE_PRECISION (enumtype) && lookup_attribute ("mode", attributes)) + { + if (precision > TYPE_PRECISION (enumtype)) + { + TYPE_PRECISION (enumtype) = 0; + error ("specified mode too small for enumeral values"); + } + else + precision = TYPE_PRECISION (enumtype); + } + else + TYPE_PRECISION (enumtype) = 0; + + if (TYPE_PACKED (enumtype) + || precision > TYPE_PRECISION (integer_type_node) + || TYPE_PRECISION (enumtype)) { tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0); if (tem == NULL) @@ -8054,17 +8071,7 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem); TYPE_ALIGN (enumtype) = TYPE_ALIGN (tem); TYPE_SIZE (enumtype) = 0; - - /* If the precision of the type was specified with an attribute and it - was too small, give an error. Otherwise, use it. */ - if (TYPE_PRECISION (enumtype) - && lookup_attribute ("mode", attributes)) - { - if (precision > TYPE_PRECISION (enumtype)) - error ("specified mode too small for enumeral values"); - } - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); + TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); layout_type (enumtype); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5d6bec01d65..924b0fbefb5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-02-04 Jakub Jelinek <jakub@redhat.com> + + PR c/69669 + * c-c++-common/pr69669.c: New test. + 2016-02-04 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/69667 diff --git a/gcc/testsuite/c-c++-common/pr69669.c b/gcc/testsuite/c-c++-common/pr69669.c new file mode 100644 index 00000000000..9940afe8ffb --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr69669.c @@ -0,0 +1,10 @@ +/* PR c/69669 */ +/* { dg-do compile } */ + +enum __attribute__((mode(QI))) E { F = 1 }; + +void +foo (enum E *x, int y) +{ + *x = (enum E) y; +} |