OSDN Git Service

2005-12-11 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / libobjc / encoding.c
index 7f6004f..1587c07 100644 (file)
@@ -222,6 +222,7 @@ objc_sizeof_type (const char *type)
       return endByte - startByte;
     }
 
+  case _C_UNION_B:
   case _C_STRUCT_B:
     {
       struct objc_struct_layout layout;
@@ -235,25 +236,6 @@ objc_sizeof_type (const char *type)
       return size;
     }
 
-  case _C_UNION_B:
-    {
-      int max_size = 0;
-      while (*type != _C_UNION_E && *type++ != '=')
-       /* do nothing */;
-      while (*type != _C_UNION_E)
-       {
-         /* Skip the variable name if any */
-         if (*type == '"')
-           {
-             for (type++; *type++ != '"';)
-               /* do nothing */;
-           }
-         max_size = MAX (max_size, objc_sizeof_type (type));
-         type = objc_skip_typespec (type);
-       }
-      return max_size;
-    }
-
   default:
     {
       objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
@@ -353,6 +335,7 @@ objc_alignof_type (const char *type)
     return objc_alignof_type (type);
 
   case _C_STRUCT_B:
+  case _C_UNION_B:
     {
       struct objc_struct_layout layout;
       unsigned int align;
@@ -365,25 +348,6 @@ objc_alignof_type (const char *type)
       return align;
     }
 
-  case _C_UNION_B:
-    {
-      int maxalign = 0;
-      while (*type != _C_UNION_E && *type++ != '=')
-       /* do nothing */;
-      while (*type != _C_UNION_E)
-       {
-         /* Skip the variable name if any */
-         if (*type == '"')
-           {
-             for (type++; *type++ != '"';)
-               /* do nothing */;
-           }
-         maxalign = MAX (maxalign, objc_alignof_type (type));
-         type = objc_skip_typespec (type);
-       }
-      return maxalign;
-    }
-
   default:
     {
       objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
@@ -762,13 +726,14 @@ objc_layout_structure (const char *type,
 {
   const char *ntype;
 
-  if (*type++ != _C_STRUCT_B)
+  if (*type != _C_UNION_B && *type != _C_STRUCT_B)
     {
       objc_error (nil, OBJC_ERR_BAD_TYPE,
-                 "record type expected in objc_layout_structure, got %s\n",
+                 "record (or union) type expected in objc_layout_structure, got %s\n",
                  type);
     }
 
+  type ++;
   layout->original_type = type;
 
   /* Skip "<name>=" if any. Avoid embedded structures and unions. */
@@ -801,13 +766,17 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
 
   /* The current type without the type qualifiers */
   const char *type;
+  BOOL unionp = layout->original_type[-1] == _C_UNION_B;
 
   /* Add the size of the previous field to the size of the record.  */
   if (layout->prev_type)
     {
       type = objc_skip_type_qualifiers (layout->prev_type);
+      if (unionp)
+        layout->record_size = MAX (layout->record_size,
+                                  objc_sizeof_type (type) * BITS_PER_UNIT);
 
-      if (*type != _C_BFLD)
+      else if (*type != _C_BFLD)
         layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
       else {
         /* Get the bitfield's type */
@@ -823,7 +792,8 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
       }
     }
 
-  if (*layout->type == _C_STRUCT_E)
+  if ((unionp && *layout->type == _C_UNION_E)
+      || (!unionp && *layout->type == _C_STRUCT_E))
     return NO;
 
   /* Skip the variable name if any */
@@ -923,7 +893,10 @@ void objc_layout_finish_structure (struct objc_struct_layout *layout,
                                    unsigned int *size,
                                    unsigned int *align)
 {
-  if (layout->type && *layout->type == _C_STRUCT_E)
+  BOOL unionp = layout->original_type[-1] == _C_UNION_B;
+  if (layout->type
+      && ((!unionp && *layout->type == _C_STRUCT_E)
+                 || (unionp && *layout->type == _C_UNION_E)))
     {
       /* Work out the alignment of the record as one expression and store
          in the record type.  Round it up to a multiple of the record's