]> gcc.gnu.org Git - gcc.git/commitdiff
class.c (check_bitfield_decl): Remove restriction on really long bitfields.
authorMark Mitchell <mark@codesourcery.com>
Sun, 19 Mar 2000 00:59:51 +0000 (00:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 19 Mar 2000 00:59:51 +0000 (00:59 +0000)
* class.c (check_bitfield_decl): Remove restriction on really long
bitfields.
(layout_class_type): Implement new ABI handling of bitfields
longer than their types.

From-SVN: r32625

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/g++.old-deja/g++.other/bitfld5.C [new file with mode: 0644]

index 79dc1c52ac4ea6b27d6af79754f447700405addb..892a466bd2ea344ae8144aa3aec75ead0b63f768 100644 (file)
@@ -1,3 +1,10 @@
+2000-03-18  Mark Mitchell  <mark@codesourcery.com>
+
+       * class.c (check_bitfield_decl): Remove restriction on really long
+       bitfields.
+       (layout_class_type): Implement new ABI handling of bitfields
+       longer than their types.
+
 2000-03-18  Martin v. Löwis  <loewis@informatik.hu-berlin.de>
 
        * parse.y (extdefs): Call ggc_collect.
index 83ece59018b896d6751455d980c4bd572fa78440..5475ac4ba9253575bbca85887e528a3c9ce90005 100644 (file)
@@ -3658,17 +3658,6 @@ check_bitfield_decl (field)
          DECL_INITIAL (field) = NULL;
          cp_error_at ("zero width for bit-field `%D'", field);
        }
-      else if (0 < compare_tree_int (w,
-                                    TYPE_PRECISION
-                                    (long_long_unsigned_type_node)))
-       {
-         /* The backend will dump if you try to use something too
-            big; avoid that.  */
-         DECL_INITIAL (field) = NULL;
-         sorry ("bit-fields larger than %d bits",
-                TYPE_PRECISION (long_long_unsigned_type_node));
-         cp_error_at ("  in declaration of `%D'", field);
-       }
       else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
               && TREE_CODE (type) != ENUMERAL_TYPE
               && TREE_CODE (type) != BOOLEAN_TYPE)
@@ -4168,8 +4157,10 @@ dfs_search_base_offsets (binfo, data)
    non-static data member of the type indicated by RLI.  BINFO is the
    binfo corresponding to the base subobject, or, if this is a
    non-static data-member, a dummy BINFO for the type of the data
-   member.  V maps offsets to types already located at those offsets.
-   This function determines the position of the DECL.  */
+   member.  BINFO may be NULL if checks to see if the field overlaps
+   an existing field with the same type are not required.  V maps
+   offsets to types already located at those offsets.  This function
+   determines the position of the DECL.  */
 
 static void
 layout_nonempty_base_or_field (rli, decl, binfo, v)
@@ -4192,7 +4183,8 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
         BINFO_OFFSET.  */
       offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
                               BITS_PER_UNIT));
-      propagate_binfo_offsets (binfo, offset);
+      if (binfo)
+       propagate_binfo_offsets (binfo, offset);
  
       /* We have to check to see whether or not there is already
         something of the same type at the offset we're about to use.
@@ -4209,10 +4201,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
         empty class, have non-zero size, any overlap can happen only
         with a direct or indirect base-class -- it can't happen with
         a data member.  */
-      if (flag_new_abi && dfs_walk (binfo,
-                                   dfs_search_base_offsets,
-                                   dfs_skip_vbases,
-                                   v))
+      if (binfo && flag_new_abi && dfs_walk (binfo,
+                                            dfs_search_base_offsets,
+                                            dfs_skip_vbases,
+                                            v))
        {
          /* Undo the propogate_binfo_offsets call.  */
          offset = convert (sizetype,
@@ -4930,6 +4922,8 @@ layout_class_type (t, empty_p, has_virtual_p,
        field = TREE_CHAIN (field))
     {
       tree binfo;
+      tree type;
+      tree padding;
 
       /* We still pass things that aren't non-static data members to
         the back-end, in case it wants to do something with them.  */
@@ -4939,11 +4933,64 @@ layout_class_type (t, empty_p, has_virtual_p,
          continue;
        }
 
+      type = TREE_TYPE (field);
+
+      /* If this field is a bit-field whose width is greater than its
+        type, then there are some special rules for allocating it
+        under the new ABI.  Under the old ABI, there were no special
+        rules, but the back-end can't handle bitfields longer than a
+        `long long', so we use the same mechanism.  */
+      if (DECL_C_BIT_FIELD (field)
+         && ((flag_new_abi 
+              && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
+             || (!flag_new_abi
+                 && compare_tree_int (DECL_SIZE (field),
+                                      TYPE_PRECISION
+                                      (long_long_unsigned_type_node)) > 0)))
+       {
+         integer_type_kind itk;
+         tree integer_type;
+
+         /* We must allocate the bits as if suitably aligned for the
+            longest integer type that fits in this many bits.  type
+            of the field.  Then, we are supposed to use the left over
+            bits as additional padding.  */
+         for (itk = itk_char; itk != itk_none; ++itk)
+           if (INT_CST_LT (DECL_SIZE (field), 
+                           TYPE_SIZE (integer_types[itk])))
+             break;
+
+         /* ITK now indicates a type that is too large for the
+            field.  We have to back up by one to find the largest
+            type that fits.  */
+         integer_type = integer_types[itk - 1];
+         padding = size_diffop (DECL_SIZE (field), 
+                                TYPE_SIZE (integer_type));
+         DECL_SIZE (field) = TYPE_SIZE (integer_type);
+         DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
+       }
+      else
+       padding = NULL_TREE;
+
       /* Create a dummy BINFO corresponding to this field.  */
-      binfo = make_binfo (size_zero_node, TREE_TYPE (field),
-                         NULL_TREE, NULL_TREE);
+      binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
       unshare_base_binfos (binfo);
       layout_nonempty_base_or_field (rli, field, binfo, v);
+
+      /* If we needed additional padding after this field, add it
+        now.  */
+      if (padding)
+       {
+         tree padding_field;
+
+         padding_field = build_decl (FIELD_DECL, 
+                                     NULL_TREE,
+                                     char_type_node); 
+         DECL_BIT_FIELD (padding_field) = 1;
+         DECL_SIZE (padding_field) = padding;
+         DECL_ALIGN (padding_field) = 1;
+         layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v);
+       }
     }
 
   /* Clean up.  */
diff --git a/gcc/testsuite/g++.old-deja/g++.other/bitfld5.C b/gcc/testsuite/g++.old-deja/g++.other/bitfld5.C
new file mode 100644 (file)
index 0000000..a9e54ec
--- /dev/null
@@ -0,0 +1,7 @@
+// Build don't link:
+// Special g++ Options: -w
+
+struct S
+{
+  int i : 1756;
+};
This page took 0.081596 seconds and 5 git commands to generate.