stor-layout.c (layout_decl): Allow front-ends to explicitly set the DECL_SIZE for...
authorMark Mitchell <mark@codesourcery.com>
Wed, 1 Mar 2000 22:29:56 +0000 (22:29 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 1 Mar 2000 22:29:56 +0000 (22:29 +0000)
* stor-layout.c (layout_decl): Allow front-ends to explicitly set
the DECL_SIZE for a FIELD_DECL.

From-SVN: r32287

gcc/ChangeLog
gcc/stor-layout.c
gcc/testsuite/g++.old-deja/g++.other/crash14.C [new file with mode: 0644]

index d5de0e7211ff83b2c1a1491a8d40a405449139f6..9ed3840623ea2438b3af89f58bb87c0f1a20b92c 100644 (file)
@@ -1,3 +1,8 @@
+2000-03-01  Mark Mitchell  <mark@codesourcery.com>
+
+       * stor-layout.c (layout_decl): Allow front-ends to explicitly set
+       the DECL_SIZE for a FIELD_DECL.
+
 2000-03-01  Bruce Korb  <bkorb@gnu.org>
 
        * fixinc/inclhack.tpl: remove unused symlinks
index 83a220abdf82c33468c742da1116e2b654dfdff1..c1187b742e912f52bb9fccd9e7eb83eaa42241bf 100644 (file)
@@ -265,30 +265,17 @@ layout_decl (decl, known_align)
 {
   register tree type = TREE_TYPE (decl);
   register enum tree_code code = TREE_CODE (decl);
-  HOST_WIDE_INT spec_size = 0;
 
   if (code == CONST_DECL)
     return;
-  else if (code == FIELD_DECL)
-    {
-      if (DECL_SIZE (decl) != 0)
-       {
-         spec_size = TREE_INT_CST_LOW (DECL_SIZE (decl));
-         DECL_SIZE (decl) = 0;
-       }
-    }
   else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
-          && code != TYPE_DECL)
+          && code != TYPE_DECL && code != FIELD_DECL)
     abort ();
 
   if (type == error_mark_node)
-    {
-      type = void_type_node;
-      spec_size = 0;
-    }
+    type = void_type_node;
 
   /* Usually the size and mode come from the data type without change.  */
-
   DECL_MODE (decl) = TYPE_MODE (type);
   TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
   if (DECL_SIZE (decl) == 0)
@@ -296,14 +283,23 @@ layout_decl (decl, known_align)
       DECL_SIZE (decl) = TYPE_SIZE (type);
       DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
     }
-
-  if (code == FIELD_DECL && DECL_BIT_FIELD (decl))
+  else if (code == FIELD_DECL)
     {
-      if (spec_size == 0 && DECL_NAME (decl) != 0)
+      HOST_WIDE_INT spec_size;
+
+      /* The front-end may set the explicit width of the field, so its
+        size may not be the same as the size of its type.  This happens
+        with bitfields, of course (an `int' bitfield may be only 2 bits,
+        say), but it also happens with other fields.  For example, the
+        C++ front-end creates zero-sized fields corresponding to empty
+        base classes, and depends on layout_type setting
+        DECL_FIELD_BITPOS correctly for the field.  */
+      if (integer_zerop (DECL_SIZE (decl)) 
+         && DECL_NAME (decl) != NULL_TREE)
        abort ();
 
       /* Size is specified in number of bits.  */
-      DECL_SIZE (decl) = bitsize_int (spec_size);
+      spec_size = TREE_INT_CST_LOW (DECL_SIZE (decl));
       if (spec_size % BITS_PER_UNIT == 0)
        DECL_SIZE_UNIT (decl) = size_int (spec_size / BITS_PER_UNIT);
       else
@@ -313,8 +309,9 @@ layout_decl (decl, known_align)
   /* Force alignment required for the data type.
      But if the decl itself wants greater alignment, don't override that.
      Likewise, if the decl is packed, don't override it.  */
-  else if (DECL_ALIGN (decl) == 0
-          || (! DECL_PACKED (decl) &&  TYPE_ALIGN (type) > DECL_ALIGN (decl)))
+  if (!(code == FIELD_DECL && DECL_BIT_FIELD (decl))
+      && (DECL_ALIGN (decl) == 0
+         || (! DECL_PACKED (decl) &&  TYPE_ALIGN (type) > DECL_ALIGN (decl))))
     DECL_ALIGN (decl) = TYPE_ALIGN (type);
 
   /* See if we can use an ordinary integer mode for a bit-field. 
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash14.C b/gcc/testsuite/g++.old-deja/g++.other/crash14.C
new file mode 100644 (file)
index 0000000..85f093d
--- /dev/null
@@ -0,0 +1,23 @@
+// Build don't link:
+// Special g++ Options: -fnew-abi
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+struct S 
+{
+};
+
+struct T : public S 
+{
+};
+
+struct U : public T 
+{
+};
+
+void f (U);
+
+int main ()
+{
+  U u;
+  f (u);
+}