diff options
author | Jakub Jelinek <jakub@redhat.com> | 2016-02-04 23:17:05 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-02-04 23:17:05 +0100 |
commit | 1066e9b53391005e86df98253d404fc60d61d841 (patch) | |
tree | 0c6d6e6c7c4474708b293d53101ea2650fe22948 | |
parent | 25f738f21021b3af025800f4481d402570d603ef (diff) | |
download | gcc-1066e9b53391005e86df98253d404fc60d61d841.zip gcc-1066e9b53391005e86df98253d404fc60d61d841.tar.gz gcc-1066e9b53391005e86df98253d404fc60d61d841.tar.bz2 |
re PR c/69669 (ICE with enum __attribute__((mode(QI))))
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.
From-SVN: r233154
-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 606b63c..931e51d 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 aaccaa8..5f6f3ee 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 5d6bec0..924b0fb 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 0000000..9940afe --- /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; +} |