* typeck.c (build_component_ref): Always complain about offsetof
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2002 19:31:23 +0000 (19:31 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2002 19:31:23 +0000 (19:31 +0000)
        constructs on non-PODs.  Only make it an error for members of
        virtual bases.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49406 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/abi/offsetof.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/friend1.C

index 63c8747..af18329 100644 (file)
@@ -1,5 +1,9 @@
 2002-02-01  Jason Merrill  <jason@redhat.com>
 
+       * typeck.c (build_component_ref): Always complain about offsetof
+       constructs on non-PODs.  Only make it an error for members of
+       virtual bases.
+
        * error.c (dump_scope): Don't add TFF_DECL_SPECIFIERS.
        (dump_function_decl): Always dump parms.
 
index 5e69b98..ba37b10 100644 (file)
@@ -1999,6 +1999,8 @@ build_component_ref (datum, component, basetype_path, protect)
   register tree ref;
   tree field_type;
   int type_quals;
+  tree old_datum;
+  tree old_basetype;
 
   if (processing_template_decl)
     return build_min_nt (COMPONENT_REF, datum, component);
@@ -2202,6 +2204,9 @@ build_component_ref (datum, component, basetype_path, protect)
   if (TREE_DEPRECATED (field))
     warn_deprecated_use (field);
 
+  old_datum = datum;
+  old_basetype = basetype;
+
   /* See if we have to do any conversions so that we pick up the field from the
      right context.  */
   if (DECL_FIELD_CONTEXT (field) != basetype)
@@ -2215,12 +2220,17 @@ build_component_ref (datum, component, basetype_path, protect)
       /* Handle base classes here...  */
       if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
        {
-         tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, NULL);
+         base_kind kind;
+         tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, &kind);
+
+         /* Complain about use of offsetof which will break.  */
          if (TREE_CODE (datum) == INDIRECT_REF
-             && integer_zerop (TREE_OPERAND (datum, 0)))
+             && integer_zerop (TREE_OPERAND (datum, 0))
+             && kind == bk_via_virtual)
            {
-             error ("invalid reference to NULL ptr, use ptr-to-member instead");
+             error ("\
+invalid offsetof from non-POD type `%#T'; use pointer to member instead",
+                    basetype);
              return error_mark_node;
            }
          datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
@@ -2239,6 +2249,18 @@ build_component_ref (datum, component, basetype_path, protect)
        }
     }
 
+  /* Complain about other invalid uses of offsetof, even though they will
+     give the right answer.  Note that we complain whether or not they
+     actually used the offsetof macro, since there's no way to know at this
+     point.  So we just give a warning, instead of a pedwarn.  */
+  if (protect
+      && CLASSTYPE_NON_POD_P (old_basetype)
+      && TREE_CODE (old_datum) == INDIRECT_REF
+      && integer_zerop (TREE_OPERAND (old_datum, 0)))
+    warning ("\
+invalid offsetof from non-POD type `%#T'; use pointer to member instead",
+            basetype);
+
   /* Compute the type of the field, as described in [expr.ref].  */
   type_quals = TYPE_UNQUALIFIED;
   field_type = TREE_TYPE (field);
diff --git a/gcc/testsuite/g++.dg/abi/offsetof.C b/gcc/testsuite/g++.dg/abi/offsetof.C
new file mode 100644 (file)
index 0000000..8a2e732
--- /dev/null
@@ -0,0 +1,22 @@
+// Test that we can refer to the address of a base member of a null pointer
+// to get its offset.  The standard says that offsetof shall not be used on
+// non-POD classes, but there seems to be no such restriction on the common
+// implementation thereof.
+
+// Yes, this is bad, naughty, evil code.  But it seems to be well-formed.
+// So we'll just warn.
+
+// { dg-do run }
+
+struct A { int i; };
+
+struct B: public A {
+  virtual void f ();
+};
+
+struct C: public B { };
+
+int main ()
+{
+  return ((unsigned long) &((C*)0)->i) != 4; // { dg-warning "offsetof" "" }
+}
index 76fcebe..f8e22c2 100644 (file)
@@ -46,10 +46,13 @@ struct R {
   X<&B::j> x;
 };
 
+B b;
+D d;
+
 void f()
 {
-    ((B*)0)->i = 3; // ERROR - protected
-    ((D*)0)->i = 4;
+    b.i = 3; // ERROR - protected
+    d.i = 4;
     B::j = 5;
     D::j = 6;
 }
@@ -57,8 +60,8 @@ void f()
 template <typename T>
 void g()
 {
-    ((B*)0)->i = 3; // ERROR - protected
-    ((D*)0)->i = 4;
+    b.i = 3; // ERROR - protected
+    d.i = 4;
     B::j = 5;
     D::j = 6;
 }
@@ -67,8 +70,8 @@ template void g<int>();
 
 void S::h()
 {
-  ((B*)0)->i = 3; // ERROR - protected
-  ((D*)0)->i = 4;
+  b.i = 3; // ERROR - protected
+  d.i = 4;
   B::j = 5;
   D::j = 6;
 }
@@ -76,8 +79,8 @@ void S::h()
 template <typename T>
 void R<T>::h() 
 {
-  ((B*)0)->i = 3; // ERROR - protected
-  ((D*)0)->i = 4;
+  b.i = 3; // ERROR - protected
+  d.i = 4;
   B::j = 5;
   D::j = 6;
 }