From 1066e9b53391005e86df98253d404fc60d61d841 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Feb 2016 23:17:05 +0100 Subject: 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 --- gcc/c/ChangeLog | 6 ++++++ gcc/c/c-decl.c | 31 +++++++++++++++++++------------ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/c-c++-common/pr69669.c | 10 ++++++++++ 4 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr69669.c 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 + + 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 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 + + PR c/69669 + * c-c++-common/pr69669.c: New test. + 2016-02-04 Michael Meissner 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; +} -- cgit v1.1