This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Add -fabi-version
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 Sep 2002 02:22:39 -0700
- Subject: C++ PATCH: Add -fabi-version
- Reply-to: mark at codesourcery dot com
An early version of CodeSourcery's C++ ABI testsuite found a new C++
ABI bug in G++:
union U {
int i: 4096;
};
This union should have size 512 on a system with 8-bit chars, but
actually only had size 508. The corresponding struct/class case works
fine; this was an interaction between unions and bit-fields whose
width is wider than that of their type.
I added detection of this case to -Wabi. Since bit-fields whose width
exceeds that of their type are incredibly rare (this feature exists
mostly to make it hard to implement the C++ ABI correctly!), and since
putting such things in a union is even rarer, I don't expect that very
many people will notice this bug.
I also added a -fabi-version flag to the C++ front end. With
-fabi-version=1, you get the G++ 3.2 ABI, which remains the default.
With -fabi=version=0, you get the version of the ABI that is closest
to the specification. There's no guarantee that ABI will remain
constant over time; it's going to change when we fix new ABI bugs.
After a while, we can set -fabi-version=2 to be the current high water
mark.
I went ahead and fixed the known ABI bugs with -fabi-version=0. But,
there are probably more lurking; we are still finding bugs on the
order of weeks, not years.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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-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-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.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.382
diff -c -p -r1.382 c-common.c
*** c-common.c 22 Sep 2002 19:23:19 -0000 1.382
--- c-common.c 23 Sep 2002 09:12:32 -0000
*************** int flag_permissive;
*** 567,572 ****
--- 567,587 ----
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: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.160
diff -c -p -r1.160 c-common.h
*** c-common.h 22 Sep 2002 02:03:14 -0000 1.160
--- c-common.h 23 Sep 2002 09:12:32 -0000
*************** extern int flag_permissive;
*** 737,742 ****
--- 737,757 ----
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: c-opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.18
diff -c -p -r1.18 c-opts.c
*** c-opts.c 15 Sep 2002 18:24:01 -0000 1.18
--- c-opts.c 23 Sep 2002 09:12:33 -0000
*************** static void sanitize_cpp_opts PARAMS ((v
*** 188,193 ****
--- 188,194 ----
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) \
*************** missing_arg (opt_index)
*** 342,347 ****
--- 343,349 ----
{
case OPT_Wformat_eq:
case OPT_d:
+ case OPT_fabi_version:
case OPT_fbuiltin_:
case OPT_fdump:
case OPT_fname_mangling:
*************** c_common_decode_option (argc, argv)
*** 1012,1017 ****
--- 1014,1023 ----
case OPT_fvtable_thunks:
case OPT_fxref:
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:
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.467
diff -c -p -r1.467 class.c
*** cp/class.c 21 Sep 2002 12:51:52 -0000 1.467
--- cp/class.c 23 Sep 2002 09:12:34 -0000
*************** layout_virtual_bases (t, offsets)
*** 4574,4580 ****
#endif
/* DSIZE is the size of the class without the virtual bases. */
! dsize = TYPE_SIZE (t);
/* Make every class have alignment of at least one. */
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
--- 4574,4583 ----
#endif
/* DSIZE is the size of the class without the virtual bases. */
! 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);
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4875,4882 ****
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));
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
--- 4878,4898 ----
field. We have to back up by one to find the largest
type that fits. */
integer_type = integer_types[itk - 1];
!
! 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);
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4944,4951 ****
padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
place_field (rli, padding);
! }
!
/* 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
--- 4960,4973 ----
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: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.751
diff -c -p -r1.751 cp-tree.h
*** cp/cp-tree.h 21 Sep 2002 12:51:53 -0000 1.751
--- cp/cp-tree.h 23 Sep 2002 09:12:35 -0000
*************** struct diagnostic_context;
*** 212,217 ****
--- 212,223 ----
#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. */
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.186
diff -c -p -r1.186 invoke.texi
*** doc/invoke.texi 22 Sep 2002 19:23:20 -0000 1.186
--- doc/invoke.texi 23 Sep 2002 09:12:38 -0000
*************** in the following sections.
*** 174,181 ****
@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
-fno-elide-constructors @gol
-fno-enforce-eh-specs -fexternal-templates @gol
-falt-external-templates @gol
--- 174,181 ----
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@gccoptlist{
! -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
*************** language supported by GCC@.
*** 1249,1254 ****
--- 1249,1263 ----
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
*************** In this case, G++ will not place @code{B
*** 1521,1526 ****
--- 1530,1548 ----
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
Index: testsuite/g++.dg/abi/bitfield6.C
===================================================================
RCS file: testsuite/g++.dg/abi/bitfield6.C
diff -N testsuite/g++.dg/abi/bitfield6.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/bitfield6.C 23 Sep 2002 09:12:38 -0000
***************
*** 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;
+ }
+
Index: testsuite/g++.dg/abi/bitfield7.C
===================================================================
RCS file: testsuite/g++.dg/abi/bitfield7.C
diff -N testsuite/g++.dg/abi/bitfield7.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/bitfield7.C 23 Sep 2002 09:12:38 -0000
***************
*** 0 ****
--- 1,7 ----
+ // { dg-do compile }
+ // { dg-options "-Wabi" }
+
+ union U { // { dg-warning "ABI" }
+ int i: 4096; // { dg-warning "exceeds" }
+ };
+
Index: testsuite/g++.dg/abi/bitfield8.C
===================================================================
RCS file: testsuite/g++.dg/abi/bitfield8.C
diff -N testsuite/g++.dg/abi/bitfield8.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/bitfield8.C 23 Sep 2002 09:12:38 -0000
***************
*** 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;
+ }
+
Index: testsuite/g++.dg/abi/vbase11.C
===================================================================
RCS file: testsuite/g++.dg/abi/vbase11.C
diff -N testsuite/g++.dg/abi/vbase11.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/vbase11.C 23 Sep 2002 09:12:38 -0000
***************
*** 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;
+ }
+