]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c-common.c (warn_abi): New variable.
authorMark Mitchell <mark@codesourcery.com>
Tue, 27 Aug 2002 22:14:51 +0000 (22:14 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 27 Aug 2002 22:14:51 +0000 (22:14 +0000)
* 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

gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-opts.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/bitfield5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/vbase10.C [new file with mode: 0644]

index e1d35dd39dc900df71a8d6437d5166363db57585..eafb6a3a46e951e4c15abba8ccf692ac8eb955b3 100644 (file)
@@ -1,3 +1,11 @@
+2002-08-27  Mark Mitchell  <mark@codesourcery.com>
+
+       * 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  <n.pero@mi.flashnet.it>
 
        * c-common.c (warn_undeclared_selector): New variable.
index 875cabcdc558579c63939b46d18271c432b1d8ae..913aec19c6b564bcce7268b30236b332cf90607c 100644 (file)
@@ -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;
index e3e4bb06cbb84a574c047431a2dfa6cb609b175a..b49e2d1a64c2fc75b96bea9e6ac288a1ae377fee 100644 (file)
@@ -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;
index bc3ae46a6d7d571c3122fc345a84bc57c6af674a..5fb8d11ee064fa441b1860865afc078e1f2e4b44 100644 (file)
@@ -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);
index def395ea1264666f9eda5a1c09d8544b9231e6fc..adb6f13d98e157f367f0056be08a6cd0036c384f 100644 (file)
@@ -1,3 +1,9 @@
+2002-08-27  Mark Mitchell  <mark@codesourcery.com>
+
+       * 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  <austern@apple.com>
 
        * tree.c (lvalue_p_1): Add argument for whether casts of lvalues
index db8cfa759200e0d5a4b5a8fe1a1d062c54372235..7cdfdafc9731f11a1751fa405e0d369a0f139000 100644 (file)
@@ -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
index 1ce61bd451d98a03f3c5ebef8a0541c9aaa98100..e956baa902af807aa7bd40283118d80cfc7539b4 100644 (file)
@@ -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
index 1e3a26295b3e1ef8602650d604c0c09c6f5de4fc..3f3a17da0701995fea3baa2dc5fafa66535d715e 100644 (file)
@@ -1,3 +1,8 @@
+2002-08-27  Mark Mitchell  <mark@codesourcery.com>
+
+       * testsuite/g++.dg/abi/bitfield5.C: New test.
+       * testsuite/g++.dg/abi/vbase10.C: Likewise.
+
 Tue Aug 27 22:23:22 2002  Nicola Pero  <n.pero@mi.flashnet.it>
 
        * 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 (file)
index 0000000..eed76e6
--- /dev/null
@@ -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 (file)
index 0000000..3c110be
--- /dev/null
@@ -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" }
+