c-common.c (flag_abi_version): New variable.
authorMark Mitchell <mark@codesourcery.com>
Mon, 23 Sep 2002 09:22:17 +0000 (09:22 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 23 Sep 2002 09:22:17 +0000 (09:22 +0000)
* c-common.c (flag_abi_version): New variable.
* c-common.h (flag_abi_version): Declare it.
* c-opts.c (missing_arg): Add -fabi-version.
(c_common_decode_option): Process -fabi-version.
* doc/invoke.texi (-fabi-version): Document it.
(-Wabi): Add information about bit-fields in unions.

* cp/class.c (layout_virtual_bases): Do not round the size of the
type to a multiple of the alignment before laying out virtual bases.
(layout_class_type): Correct handling of bit-fields that are wider
than their type inside unions.  Round the size of the type to a
even number of bytes when computing the size without virtual
bases.
* cp/cp-tree.h (abi_version_at_least): New macro.

* g++.dg/abi/bitfield6.C: New test.
* g++.dg/abi/bitfield7.C: New test.
* g++.dg/abi/bitfield8.C: New test.
* g++.dg/abi/vbase11.C: New test.

From-SVN: r57432

13 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-opts.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/bitfield6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/bitfield7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/bitfield8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/vbase11.C [new file with mode: 0644]

index 2e0326068ec9909f37c294cc66a836dedbf961d7..fd6d5ad45f558eb76d9f79c8a409032150896bed 100644 (file)
@@ -1,3 +1,12 @@
+2002-09-23  Mark Mitchell  <mark@codesourcery.com>
+
+       * c-common.c (flag_abi_version): New variable.
+       * c-common.h (flag_abi_version): Declare it.
+       * c-opts.c (missing_arg): Add -fabi-version.
+       (c_common_decode_option): Process -fabi-version.
+       * doc/invoke.texi (-fabi-version): Document it.
+       (-Wabi): Add information about bit-fields in unions.
+       
 2002-09-22  Jason Thorpe  <thorpej@wasabisystems.com>
 
        * config/mips/netbsd.h (SUBTARGET_ASM_SPEC): Always pass -KPIC
index c85c23c8eca46cf7d99e052df0d65a9d4972856c..251a2551575c79e0b22662ed58b3aee36c35084b 100644 (file)
@@ -567,6 +567,21 @@ int flag_permissive;
 
 int flag_enforce_eh_specs = 1;
 
+/*  The version of the C++ ABI in use.  The following values are
+    allowed:
+
+    0: The version of the ABI believed most conformant with the 
+       C++ ABI specification.  This ABI may change as bugs are
+       discovered and fixed.  Therefore, 0 will not necessarily
+       indicate the same ABI in different versions of G++.
+
+    1: The version of the ABI first used in G++ 3.2.
+
+    Additional positive integers will be assigned as new versions of
+    the ABI become the default version of the ABI.  */
+
+int flag_abi_version = 1;
+
 /* Nonzero means warn about things that will change when compiling
    with an ABI-compliant compiler.  */
 
index f15dbf18bf50377c7624fb1419f691df6180674e..8cf6aa47ce85417fe80004dd913aac9cdbcf110f 100644 (file)
@@ -737,6 +737,21 @@ extern int flag_permissive;
 
 extern int flag_enforce_eh_specs;
 
+/*  The version of the C++ ABI in use.  The following values are
+    allowed:
+
+    -1: The version of the ABI believed most conformant with the 
+        C++ ABI specification.  This ABI may change as bugs are
+       discovered and fixed.  Therefore, -1 will not necessarily
+       indicate the same ABI in different versions of G++.
+
+    0: The version of the ABI first used in G++ 3.2.
+
+    Additional positive integers will be assigned as new versions of
+    the ABI become the default version of the ABI.  */
+
+extern int flag_abi_version;
+
 /* Nonzero means warn about things that will change when compiling
    with an ABI-compliant compiler.  */
 
index ce4b910d03ba5bd5015b96a818762aef482b84fe..4d9e3d2dcf6bc07da1676552990ecef4ed94f92c 100644 (file)
@@ -188,6 +188,7 @@ static void sanitize_cpp_opts PARAMS ((void));
   OPT("Wwrite-strings",                CL_ALL,   OPT_Wwrite_strings)                \
   OPT("ansi",                  CL_ALL,   OPT_ansi)                          \
   OPT("d",                      CL_ALL | CL_JOINED, OPT_d)                  \
+  OPT("fabi-version=",          CL_CXX | CL_JOINED, OPT_fabi_version)        \
   OPT("faccess-control",       CL_CXX,   OPT_faccess_control)               \
   OPT("fall-virtual",          CL_CXX,   OPT_fall_virtual)                  \
   OPT("falt-external-templates",CL_CXX,   OPT_falt_external_templates)      \
@@ -342,6 +343,7 @@ missing_arg (opt_index)
     {
     case OPT_Wformat_eq:
     case OPT_d:
+    case OPT_fabi_version:
     case OPT_fbuiltin_:
     case OPT_fdump:
     case OPT_fname_mangling:
@@ -1014,6 +1016,10 @@ c_common_decode_option (argc, argv)
       warning ("switch \"%s\" is no longer supported", argv[0]);
       break;
 
+    case OPT_fabi_version:
+      flag_abi_version = read_integral_parameter (arg, argv[0], 1);
+      break;
+
     case OPT_faccess_control:
       flag_access_control = on;
       break;
index 634ccbbba3e5ff227e560b68e4c2e81b0fb8c287..a25c6aa8b3fcf9c90c63d345fbc320c4d7ea0775 100644 (file)
@@ -1,3 +1,13 @@
+2002-09-23  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp/class.c (layout_virtual_bases): Do not round the size of the
+       type to a multiple of the alignment before laying out virtual bases.
+       (layout_class_type): Correct handling of bit-fields that are wider
+       than their type inside unions.  Round the size of the type to a
+       even number of bytes when computing the size without virtual
+       bases.
+       * cp/cp-tree.h (abi_version_at_least): New macro.
+       
 2002-09-21  Kazu Hirata  <kazu@cs.umass.edu>
 
        * ChangeLog: Follow spelling conventions.
index 7f365e76899873004d65380e7a50f0cb07f6bbff..316bc63f99d51cfaa0fd54850be3a569ef36962e 100644 (file)
@@ -4574,7 +4574,10 @@ layout_virtual_bases (t, offsets)
 #endif
 
   /* DSIZE is the size of the class without the virtual bases.  */
-  dsize = TYPE_SIZE (t);
+  if (abi_version_at_least(2))
+    dsize = CLASSTYPE_SIZE (t);
+  else
+    dsize = TYPE_SIZE (t);
 
   /* Make every class have alignment of at least one.  */
   TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
@@ -4875,8 +4878,21 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
             field.  We have to back up by one to find the largest
             type that fits.  */
          integer_type = integer_types[itk - 1];
-         padding = size_binop (MINUS_EXPR, DECL_SIZE (field), 
-                               TYPE_SIZE (integer_type));
+
+         if (abi_version_at_least (2) && TREE_CODE (t) == UNION_TYPE)
+           /* In a union, the padding field must have the full width
+              of the bit-field; all fields start at offset zero.  */
+           padding = DECL_SIZE (field);
+         else
+           {
+             if (warn_abi && TREE_CODE (t) == UNION_TYPE)
+               warning ("size assigned to `%T' may not be "
+                        "ABI-compliant and may change in a future "
+                        "version of GCC", 
+                        t);
+             padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+                                   TYPE_SIZE (integer_type));
+           }
          DECL_SIZE (field) = TYPE_SIZE (integer_type);
          DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
          DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
@@ -4944,8 +4960,14 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
 
       padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
       place_field (rli, padding);
-    }
-
+    } 
+  else if (abi_version_at_least (2)
+          && !integer_zerop (rli->bitpos))
+    /* Make sure that we are on a byte boundary so that the size of
+       the class without virtual bases will always be a round number
+       of bytes.  */
+    rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+  
   /* Let the back-end lay out the type. Note that at this point we
      have only included non-virtual base-classes; we will lay out the
      virtual base classes later.  So, the TYPE_SIZE/TYPE_ALIGN after
index 077dec4298d17c41545df6cf7e0dba7b262eda11..b3cee372697144fcdc97002f978064fe4b4f9b71 100644 (file)
@@ -212,6 +212,12 @@ struct diagnostic_context;
 
 #endif
 
+/* Returns TRUE if generated code should match ABI version N or
+   greater is in use.  */
+
+#define abi_version_at_least(N) \
+  (flag_abi_version == 0 || flag_abi_version >= (N))
+
 \f
 /* Language-dependent contents of an identifier.  */
 
index f1ddd5d68c4b35baa9696f42cd3dc526f55a7c88..66aab29a30da2afa37c4af66d415e979baff7388 100644 (file)
@@ -174,8 +174,8 @@ in the following sections.
 @item C++ Language Options
 @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
 @gccoptlist{
--fno-access-control  -fcheck-new  -fconserve-space @gol
--fno-const-strings  -fdollars-in-identifiers @gol
+-fabi-version=@var{n} -fno-access-control  -fcheck-new @gol
+-fconserve-space -fno-const-strings  -fdollars-in-identifiers @gol
 -fno-elide-constructors @gol
 -fno-enforce-eh-specs  -fexternal-templates @gol
 -falt-external-templates @gol
@@ -1249,6 +1249,15 @@ language supported by GCC@.
 Here is a list of options that are @emph{only} for compiling C++ programs:
 
 @table @gcctabopt
+
+@item -fabi-version=@var{n}
+@opindex fabi-version
+Use version @var{n} of the C++ ABI.  Version 1 is the version of the C++
+ABI that first appeared in G++ 3.2.  Version 0 will always be the
+version that conforms most closely to the C++ ABI specification.
+Therefore, the ABI obtained using version 0 will change as ABI bugs are
+fixed.
+
 @item -fno-access-control
 @opindex fno-access-control
 Turn off all access checking.  This switch is mainly useful for working
@@ -1522,6 +1531,19 @@ explicitly padding @code{A} so that its size is a multiple of its
 alignment (ignoring virtual base classes); that will cause G++ and other
 compilers to layout @code{C} identically.
 
+@item
+Incorrect handling of bit-fields with declared widths greater than that
+of their underlying types, when the bit-fields appear in a union.  For
+example:
+
+@smallexample
+union U @{ int i : 4096; @};
+@end smallexample
+
+@noindent
+Assuming that an @code{int} does not have 4096 bits, G++ will make the
+union too small by the number of bits in an @code{int}.
+
 @end itemize
 
 @item -Wctor-dtor-privacy @r{(C++ only)}
index 83843fef3837f89a68a9d72b759497cdc218a612..19d87b3e9dc3c2f02cead7ade2e19328d1f90263 100644 (file)
@@ -1,3 +1,10 @@
+2002-09-23  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/bitfield6.C: New test.
+       * g++.dg/abi/bitfield7.C: New test.
+       * g++.dg/abi/bitfield8.C: New test.
+       * g++.dg/abi/vbase11.C: New test.
+
 2002-09-22  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * gcc.dg/20020219-1.c: Add "-mdisable-indexing" option for target
diff --git a/gcc/testsuite/g++.dg/abi/bitfield6.C b/gcc/testsuite/g++.dg/abi/bitfield6.C
new file mode 100644 (file)
index 0000000..50f76ab
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-do run }
+// { dg-options "-w -fabi-version=0" }
+
+#include <limits>
+
+union U {
+  int i: 4096;
+};
+
+int main () {
+  if (sizeof (U) * std::numeric_limits<unsigned char>::digits != 4096)
+    return 1;
+}
+
diff --git a/gcc/testsuite/g++.dg/abi/bitfield7.C b/gcc/testsuite/g++.dg/abi/bitfield7.C
new file mode 100644 (file)
index 0000000..9868cfc
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-Wabi" }
+
+union U { // { dg-warning "ABI" }
+  int i: 4096; // { dg-warning "exceeds" }
+};
+
diff --git a/gcc/testsuite/g++.dg/abi/bitfield8.C b/gcc/testsuite/g++.dg/abi/bitfield8.C
new file mode 100644 (file)
index 0000000..8195fda
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do run { target i?86-*-* } }
+// { dg-options "-fabi-version=0" }
+
+struct A { 
+  virtual void f() {}
+  int f1 : 1; 
+};
+
+struct B : public A {
+  int f2 : 31;
+  int f3 : 4; 
+  int f4 : 3;
+};
+
+int main ()
+{
+  if (sizeof (B) != 16)
+    return 1;
+}
+  
diff --git a/gcc/testsuite/g++.dg/abi/vbase11.C b/gcc/testsuite/g++.dg/abi/vbase11.C
new file mode 100644 (file)
index 0000000..3755773
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do run { target i?86-*-* } }
+// { dg-options "-fabi-version=0" }
+
+struct A { virtual void f(); char c1; };
+struct B { B(); char c2; };
+struct C : public A, public virtual B { };
+
+int main () {
+  if (sizeof (C) != 8)
+    return 1;
+}
+