C++ PATCH: Rest DECL_MODE for over-long bitfields
Mark Mitchell
mark@codesourcery.com
Mon Sep 15 00:26:00 GMT 2003
When layout a class like:
struct S {
char c : 124;
};
we temporarily give the FIELD_DECL for "c" a different type, so as to
implement the C++ ABI rules (which treat "c" as if it had the
alignment of "long long" in this case).
We were resetting the DECL_SIZE -- but not the DECL_MODE -- for the
FIELD_DECL when we were done.
This resulted in using 2-byte store instructions to write to the
field, even though all but the first 8 bits are padding. On a
big-endian machine, that's disastrous; it means that an incorrect
value is being written to the bit-field. Our C++ ABI Testsuite caught
this bug.
This is an ABI change -- although the layout will be identical,
different bits will be used to store the field. Therefore, this
change is guarded with flag_abi_version.
Tested on i686-pc-linux-gnu and ia64-hp-hpux11.22, applied on the
mainline and on the branch. (On the branch, we want the -Wabi
warning, and there is no reason not to have the -fabi-version=0 fix as
well.)
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-09-14 Mark Mitchell <mark@codesourcery.com>
* class.c (layout_class_type): Make DECL_MODE match TYPE_MODE for
an bit-field whose width exceeds that of its type.
2003-09-14 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/bitfield11.C: New test.
* g++.dg/abi/bitfield12.C: Likewise.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.569
diff -c -5 -p -r1.569 class.c
*** class.c 11 Sep 2003 15:18:46 -0000 1.569
--- class.c 15 Sep 2003 00:23:36 -0000
*************** layout_class_type (tree t, tree *virtual
*** 4757,4766 ****
--- 4757,4775 ----
DECL_NAME (field) = NULL_TREE;
/* Now that layout has been performed, set the size of the
field to the size of its declared type; the rest of the
field is effectively invisible. */
DECL_SIZE (field) = TYPE_SIZE (type);
+ /* We must also reset the DECL_MODE of the field. */
+ if (abi_version_at_least (2))
+ DECL_MODE (field) = TYPE_MODE (type);
+ else if (warn_abi
+ && DECL_MODE (field) != TYPE_MODE (type))
+ /* Versions of G++ before G++ 3.4 did not reset the
+ DECL_MODE. */
+ warning ("the offset of `%D' may not be ABI-compliant and may "
+ "change in a future version of GCC", field);
}
else
layout_nonempty_base_or_field (rli, field, NULL_TREE,
empty_base_offsets);
Index: testsuite/g++.dg/abi/bitfield11.C
===================================================================
RCS file: testsuite/g++.dg/abi/bitfield11.C
diff -N testsuite/g++.dg/abi/bitfield11.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/bitfield11.C 15 Sep 2003 00:24:36 -0000
***************
*** 0 ****
--- 1,14 ----
+ // { dg-do run }
+ // { dg-options "-w -fabi-version=0" }
+
+ struct S {
+ char c : 1024;
+ };
+
+ S s;
+
+ int main () {
+ s.c = 1;
+ if (*(char *)&s != 1)
+ return 1;
+ }
Index: testsuite/g++.dg/abi/bitfield12.C
===================================================================
RCS file: testsuite/g++.dg/abi/bitfield12.C
diff -N testsuite/g++.dg/abi/bitfield12.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/bitfield12.C 15 Sep 2003 00:24:36 -0000
***************
*** 0 ****
--- 1,5 ----
+ // { dg-options "-Wabi -fabi-version=1" }
+
+ struct S { // { dg-warning "ABI" }
+ char c : 1024; // { dg-warning "width" }
+ };
More information about the Gcc-patches
mailing list