diff options
author | Mark Mitchell <mark@codesourcery.com> | 2002-09-23 09:22:17 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-09-23 09:22:17 +0000 |
commit | 2d3e278d62b7568a5a4b775dc42c74f051cd1edb (patch) | |
tree | 1a0a4c88a7ec146d17c908d2c4246c6c718372b8 | |
parent | d4e81c8598c969b31734b38a2f1dfcf563725c5b (diff) | |
download | gcc-2d3e278d62b7568a5a4b775dc42c74f051cd1edb.zip gcc-2d3e278d62b7568a5a4b775dc42c74f051cd1edb.tar.gz gcc-2d3e278d62b7568a5a4b775dc42c74f051cd1edb.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c-common.c | 15 | ||||
-rw-r--r-- | gcc/c-common.h | 15 | ||||
-rw-r--r-- | gcc/c-opts.c | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/class.c | 32 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/bitfield6.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/bitfield7.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/bitfield8.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/vbase11.C | 12 |
13 files changed, 172 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2e03260..fd6d5ad4 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 c85c23c..251a255 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 f15dbf1..8cf6aa4 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 ce4b910..4d9e3d2 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 634ccbb..a25c6aa 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 7f365e7..316bc63 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 077dec4..b3cee37 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 f1ddd5d..66aab29 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 83843fe..19d87b3 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 0000000..50f76ab --- /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 0000000..9868cfc --- /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 0000000..8195fda --- /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 0000000..3755773 --- /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; +} + |