From 2d3e278d62b7568a5a4b775dc42c74f051cd1edb Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Mon, 23 Sep 2002 09:22:17 +0000
Subject: [PATCH] c-common.c (flag_abi_version): New variable.

	* 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
---
 gcc/ChangeLog                        |  9 ++++++++
 gcc/c-common.c                       | 15 +++++++++++++
 gcc/c-common.h                       | 15 +++++++++++++
 gcc/c-opts.c                         |  6 ++++++
 gcc/cp/ChangeLog                     | 10 +++++++++
 gcc/cp/class.c                       | 32 +++++++++++++++++++++++-----
 gcc/cp/cp-tree.h                     |  6 ++++++
 gcc/doc/invoke.texi                  | 26 ++++++++++++++++++++--
 gcc/testsuite/ChangeLog              |  7 ++++++
 gcc/testsuite/g++.dg/abi/bitfield6.C | 14 ++++++++++++
 gcc/testsuite/g++.dg/abi/bitfield7.C |  7 ++++++
 gcc/testsuite/g++.dg/abi/bitfield8.C | 20 +++++++++++++++++
 gcc/testsuite/g++.dg/abi/vbase11.C   | 12 +++++++++++
 13 files changed, 172 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/bitfield6.C
 create mode 100644 gcc/testsuite/g++.dg/abi/bitfield7.C
 create mode 100644 gcc/testsuite/g++.dg/abi/bitfield8.C
 create mode 100644 gcc/testsuite/g++.dg/abi/vbase11.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2e0326068ec9..fd6d5ad45f55 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-common.c b/gcc/c-common.c
index c85c23c8eca4..251a2551575c 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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.  */
 
diff --git a/gcc/c-common.h b/gcc/c-common.h
index f15dbf18bf50..8cf6aa47ce85 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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.  */
 
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index ce4b910d03ba..4d9e3d2dcf6b 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -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;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 634ccbbba3e5..a25c6aa8b3fc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 7f365e768998..316bc63f99d5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 077dec4298d1..b3cee3726971 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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))
+
 
 /* Language-dependent contents of an identifier.  */
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f1ddd5d68c4b..66aab29a30da 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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)}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 83843fef3837..19d87b3e9dc3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 000000000000..50f76ab824bc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/bitfield6.C
@@ -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
index 000000000000..9868cfce1987
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/bitfield7.C
@@ -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
index 000000000000..8195fda631d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/bitfield8.C
@@ -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
index 000000000000..375577365a37
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/vbase11.C
@@ -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;
+}
+
-- 
GitLab