From: Mark Mitchell Date: Tue, 27 Aug 2002 22:14:51 +0000 (+0000) Subject: c-common.c (warn_abi): New variable. X-Git-Tag: releases/gcc-3.3.0~3137 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=eca7f13c6953706b97f6158dcef99f0566f1fbb5;p=thirdparty%2Fgcc.git c-common.c (warn_abi): New variable. * c-common.c (warn_abi): New variable. * c-common.h (warn_abi): Likewise. * c-opts.c (COMMAND_LINE_OPTIONS): Add -Wabi. (c_common_decode_option): Handle it. * doc/invoke.texi:P Document -Wabi. * class.c (layout_virtual_bases): Warn about bugs in G++ that result in incorrect object layouts. (layout_class_type): Likewise. * testsuite/g++.dg/abi/bitfield5.C: New test. * testsuite/g++.dg/abi/vbase10.C: Likewise. From-SVN: r56618 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e1d35dd39dc9..eafb6a3a46e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2002-08-27 Mark Mitchell + + * c-common.c (warn_abi): New variable. + * c-common.h (warn_abi): Likewise. + * c-opts.c (COMMAND_LINE_OPTIONS): Add -Wabi. + (c_common_decode_option): Handle it. + * doc/invoke.texi:P Document -Wabi. + Tue Aug 27 23:03:52 2002 Nicola Pero * c-common.c (warn_undeclared_selector): New variable. diff --git a/gcc/c-common.c b/gcc/c-common.c index 875cabcdc558..913aec19c6b5 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -566,6 +566,11 @@ int flag_permissive; int flag_enforce_eh_specs = 1; +/* Nonzero means warn about things that will change when compiling + with an ABI-compliant compiler. */ + +int warn_abi = 0; + /* Nonzero means warn about implicit declarations. */ int warn_implicit = 1; diff --git a/gcc/c-common.h b/gcc/c-common.h index e3e4bb06cbb8..b49e2d1a64c2 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -737,6 +737,11 @@ extern int flag_permissive; extern int flag_enforce_eh_specs; +/* Nonzero means warn about things that will change when compiling + with an ABI-compliant compiler. */ + +extern int warn_abi; + /* Nonzero means warn about implicit declarations. */ extern int warn_implicit; diff --git a/gcc/c-opts.c b/gcc/c-opts.c index bc3ae46a6d7d..5fb8d11ee064 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -124,6 +124,7 @@ static void sanitize_cpp_opts PARAMS ((void)); OPT("MQ", CL_ALL | CL_ARG, OPT_MQ) \ OPT("MT", CL_ALL | CL_ARG, OPT_MT) \ OPT("P", CL_ALL, OPT_P) \ + OPT("Wabi", CL_CXX, OPT_Wabi) \ OPT("Wall", CL_ALL, OPT_Wall) \ OPT("Wbad-function-cast", CL_C, OPT_Wbad_function_cast) \ OPT("Wcast-qual", CL_ALL, OPT_Wcast_qual) \ @@ -684,6 +685,10 @@ c_common_decode_option (argc, argv) cpp_opts->no_line_commands = 1; break; + case OPT_Wabi: + warn_abi = on; + break; + case OPT_Wall: set_Wunused (on); set_Wformat (on); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index def395ea1264..adb6f13d98e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2002-08-27 Mark Mitchell + + * class.c (layout_virtual_bases): Warn about bugs in G++ that + result in incorrect object layouts. + (layout_class_type): Likewise. + 2002-08-24 Matt Austern * tree.c (lvalue_p_1): Add argument for whether casts of lvalues diff --git a/gcc/cp/class.c b/gcc/cp/class.c index db8cfa759200..7cdfdafc9731 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4562,6 +4562,7 @@ layout_virtual_bases (t, offsets) { tree vbases, dsize; unsigned HOST_WIDE_INT eoc; + bool first_vbase = true; if (CLASSTYPE_N_BASECLASSES (t) == 0) return; @@ -4589,6 +4590,7 @@ layout_virtual_bases (t, offsets) if (!TREE_VIA_VIRTUAL (vbases)) continue; + vbase = binfo_for_vbase (BINFO_TYPE (vbases), t); if (!BINFO_PRIMARY_P (vbase)) @@ -4606,7 +4608,6 @@ layout_virtual_bases (t, offsets) /* Add padding so that we can put the virtual base class at an appropriately aligned offset. */ dsize = round_up (dsize, desired_align); - usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node); /* We try to squish empty virtual bases in just like @@ -4634,11 +4635,30 @@ layout_virtual_bases (t, offsets) CLASSTYPE_SIZE (basetype))); } + /* If the first virtual base might have been placed at a + lower address, had we started from CLASSTYPE_SIZE, rather + than TYPE_SIZE, issue a warning. There can be both false + positives and false negatives from this warning in rare + cases; to deal with all the possibilities would probably + require performing both layout algorithms and comparing + the results which is not particularly tractable. */ + if (warn_abi + && first_vbase + && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR, + round_up (CLASSTYPE_SIZE (t), + desired_align), + bitsize_unit_node), + BINFO_OFFSET (vbase))) + warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC", + basetype); + /* Keep track of the offsets assigned to this virtual base. */ record_subobject_offsets (BINFO_TYPE (vbase), BINFO_OFFSET (vbase), offsets, /*vbases_p=*/0); + + first_vbase = false; } } @@ -4776,6 +4796,8 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of types that appear at that offset. */ splay_tree empty_base_offsets; + /* True if the last field layed out was a bit-field. */ + bool last_field_was_bitfield = false; /* Keep track of the first non-static data member. */ non_static_data_members = TYPE_FIELDS (t); @@ -4865,6 +4887,18 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) layout_nonempty_base_or_field (rli, field, NULL_TREE, empty_base_offsets, t); + /* If a bit-field does not immediately follow another bit-field, + and yet it starts in the middle of a byte, we have failed to + comply with the ABI. */ + if (warn_abi + && DECL_C_BIT_FIELD (field) + && !last_field_was_bitfield + && !integer_zerop (size_binop (TRUNC_MOD_EXPR, + DECL_FIELD_BIT_OFFSET (field), + bitsize_unit_node))) + cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC", + field); + /* If we needed additional padding after this field, add it now. */ if (padding) @@ -4882,6 +4916,8 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p) NULL_TREE, empty_base_offsets, t); } + + last_field_was_bitfield = DECL_C_BIT_FIELD (field); } /* It might be the case that we grew the class to allocate a diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1ce61bd451d9..e956baa902af 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -187,7 +187,7 @@ in the following sections. -fno-optional-diags -fpermissive @gol -frepo -fno-rtti -fstats -ftemplate-depth-@var{n} @gol -fuse-cxa-atexit -fvtable-gc -fno-weak -nostdinc++ @gol --fno-default-inline -Wctor-dtor-privacy @gol +-fno-default-inline -Wabi -Wctor-dtor-privacy @gol -Wnon-virtual-dtor -Wreorder @gol -Weffc++ -Wno-deprecated @gol -Wno-non-template-friend -Wold-style-cast @gol @@ -211,7 +211,7 @@ in the following sections. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{ -fsyntax-only -pedantic -pedantic-errors @gol --w -W -Wall -Waggregate-return @gol +-w -W -Wall -Waggregate-return @gol -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment @gol -Wconversion -Wno-deprecated-declarations @gol -Wdisabled-optimization -Wno-div-by-zero -Werror @gol @@ -1475,6 +1475,58 @@ Do not assume @samp{inline} for functions defined inside a class scope. functions will have linkage like inline functions; they just won't be inlined by default. +@item -Wabi @r{(C++ only)} +@opindex Wabi +Warn when G++ generates code that is probably not compatible with the +vendor-neutral C++ ABI. Although an effort has been made to warn about +all such cases, there are probably some cases that are not warned about, +even though G++ is generating incompatible code. There may also be +cases where warnings are emitted even though the code that is generated +will be compatible. + +You should rewrite your code to avoid these warnings if you are +concerned about the fact that code generated by G++ may not be binary +compatible with code generated by other compilers. + +The known incompatibilites at this point include: + +@itemize @bullet + +@item +Incorrect handling of tail-padding for bit-fields. G++ may attempt to +pack data into the same byte as a base class. For example: + +@smallexample +struct A @{ virtual void f(); int f1 : 1; @}; +struct B : public A @{ int f2 : 1; @}; +@end smallexample + +@noindent +In this case, G++ will place @code{B::f2} into the same byte +as@code{A::f1}; other compilers will not. You can avoid this problem +by explicitly padding @code{A} so that its size is a multiple of the +byte size on your platform; that will cause G++ and other compilers to +layout @code{B} identically. + +@item +Incorrect handling of tail-padding for virtual bases. G++ does not use +tail padding when laying out virtual bases. For example: + +@smallexample +struct A @{ virtual void f(); char c1; @}; +struct B @{ B(); char c2; @}; +struct C : public A, public virtual B @{@}; +@end smallexample + +@noindent +In this case, G++ will not place @code{B} into the tail-padding for +@code{A}; other compilers will. You can avoid this problem by +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. + +@end itemize + @item -Wctor-dtor-privacy @r{(C++ only)} @opindex Wctor-dtor-privacy Warn when a class seems unusable, because all the constructors or diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1e3a26295b3e..3f3a17da0701 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-08-27 Mark Mitchell + + * testsuite/g++.dg/abi/bitfield5.C: New test. + * testsuite/g++.dg/abi/vbase10.C: Likewise. + Tue Aug 27 22:23:22 2002 Nicola Pero * objc.dg/undeclared-selector.m: New test. diff --git a/gcc/testsuite/g++.dg/abi/bitfield5.C b/gcc/testsuite/g++.dg/abi/bitfield5.C new file mode 100644 index 000000000000..eed76e649e6e --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/bitfield5.C @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-Wabi" } + +struct A { + virtual void f(); + int f1 : 1; +}; + +struct B : public A { + int f2 : 1; // { dg-warning "ABI" } + int : 0; + int f3 : 4; + int f4 : 3; +}; diff --git a/gcc/testsuite/g++.dg/abi/vbase10.C b/gcc/testsuite/g++.dg/abi/vbase10.C new file mode 100644 index 000000000000..3c110be71885 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/vbase10.C @@ -0,0 +1,7 @@ +// { dg-do compile } +// { dg-options "-Wabi" } + +struct A { virtual void f(); char c1; }; +struct B { B(); char c2; }; +struct C : public A, public virtual B {}; // { dg-warning "ABI" } +