re PR c/69669 (ICE with enum __attribute__((mode(QI))))
authorJakub Jelinek <jakub@redhat.com>
Thu, 4 Feb 2016 22:17:05 +0000 (23:17 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 4 Feb 2016 22:17:05 +0000 (23:17 +0100)
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
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr69669.c [new file with mode: 0644]

index 606b63c72946ed03a4094ce7530f53610227c5c6..931e51d03d86de3fc089319925ce9da5c1fe44f2 100644 (file)
@@ -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
index aaccaa880066282d347a717b5500494e034ae41c..5f6f3ee2ad7d47824e3acbf52cb198a50a0320d4 100644 (file)
@@ -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);
 
index 5d6bec01d651da77c1ed0076a264b47290eded76..924b0fbefb568537c3de772ada19e0aa822f612e 100644 (file)
@@ -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 (file)
index 0000000..9940afe
--- /dev/null
@@ -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;
+}