From: jakub Date: Thu, 4 Feb 2016 22:17:05 +0000 (+0000) Subject: PR c/69669 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6b098e91f55238b31ed7eb28741ef1b96d198046;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 606b63c72946..931e51d03d86 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 aaccaa880066..5f6f3ee2ad7d 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 5d6bec01d651..924b0fbefb56 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 000000000000..9940afe8ffb8 --- /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; +}