OSDN Git Service

2005-12-16 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index 65d98f8..b4e9ad1 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
@@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
+#include "output.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "target.h"
@@ -451,10 +452,10 @@ layout_decl (tree decl, unsigned int known_align)
          int size_as_int = TREE_INT_CST_LOW (size);
 
          if (compare_tree_int (size, size_as_int) == 0)
-           warning (0, "%Jsize of %qD is %d bytes", decl, decl, size_as_int);
+           warning (0, "size of %q+D is %d bytes", decl, size_as_int);
          else
-           warning (0, "%Jsize of %qD is larger than %d bytes",
-                     decl, decl, larger_than_size);
+           warning (0, "size of %q+D is larger than %wd bytes",
+                     decl, larger_than_size);
        }
     }
 
@@ -799,9 +800,19 @@ place_field (record_layout_info rli, tree field)
   /* The type of this field.  */
   tree type = TREE_TYPE (field);
 
-  if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
-      return;
+  gcc_assert (TREE_CODE (field) != ERROR_MARK);
 
+  if (TREE_CODE (type) == ERROR_MARK)
+    {
+      if (TREE_CODE (field) == FIELD_DECL)
+       {
+         DECL_FIELD_OFFSET (field) = size_int (0);
+         DECL_FIELD_BIT_OFFSET (field) = bitsize_int (0);
+       }
+      
+      return;
+    }
+  
   /* If FIELD is static, then treat it like a separate variable, not
      really like a structure field.  If it is a FUNCTION_DECL, it's a
      method.  In both cases, all we do is lay out the decl, and we do
@@ -851,11 +862,11 @@ place_field (record_layout_info rli, tree field)
          if (TYPE_ALIGN (type) > desired_align)
            {
              if (STRICT_ALIGNMENT)
-               warning (0, "%Jpacked attribute causes inefficient alignment "
-                         "for %qD", field, field);
+               warning (OPT_Wattributes, "packed attribute causes "
+                         "inefficient alignment for %q+D", field);
              else
-               warning (0, "%Jpacked attribute is unnecessary for %qD",
-                        field, field);
+               warning (OPT_Wattributes, "packed attribute is "
+                        "unnecessary for %q+D", field);
            }
        }
       else
@@ -869,7 +880,7 @@ place_field (record_layout_info rli, tree field)
       /* No, we need to skip space before this field.
         Bump the cumulative size to multiple of field alignment.  */
 
-      warning (OPT_Wpadded, "%Jpadding struct to align %qD", field, field);
+      warning (OPT_Wpadded, "padding struct to align %q+D", field);
 
       /* If the alignment is still within offset_align, just align
         the bit position.  */
@@ -1266,9 +1277,9 @@ finalize_record_size (record_layout_info rli)
   TYPE_SIZE_UNIT (rli->t)
     = round_up (unpadded_size_unit, TYPE_ALIGN_UNIT (rli->t));
 
-  if (warn_padded && TREE_CONSTANT (unpadded_size)
+  if (TREE_CONSTANT (unpadded_size)
       && simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
-    warning (0, "padding struct size to alignment boundary");
+    warning (OPT_Wpadded, "padding struct size to alignment boundary");
 
   if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
       && TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary
@@ -1298,17 +1309,19 @@ finalize_record_size (record_layout_info rli)
                name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rli->t)));
 
              if (STRICT_ALIGNMENT)
-               warning (0, "packed attribute causes inefficient "
+               warning (OPT_Wpacked, "packed attribute causes inefficient "
                         "alignment for %qs", name);
              else
-               warning (0, "packed attribute is unnecessary for %qs", name);
+               warning (OPT_Wpacked,
+                        "packed attribute is unnecessary for %qs", name);
            }
          else
            {
              if (STRICT_ALIGNMENT)
-               warning (0, "packed attribute causes inefficient alignment");
+               warning (OPT_Wpacked,
+                        "packed attribute causes inefficient alignment");
              else
-               warning (0, "packed attribute is unnecessary");
+               warning (OPT_Wpacked, "packed attribute is unnecessary");
            }
        }
     }
@@ -1364,14 +1377,15 @@ compute_record_mode (tree type)
 #endif /* MEMBER_TYPE_FORCES_BLK  */
     }
 
-  TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
-
   /* If we only have one real field; use its mode if that mode's size
      matches the type's size.  This only applies to RECORD_TYPE.  This
      does not apply to unions.  */
   if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
-      && GET_MODE_SIZE (mode) == GET_MODE_SIZE (TYPE_MODE (type)))
+      && host_integerp (TYPE_SIZE (type), 1)
+      && GET_MODE_BITSIZE (mode) == TREE_INT_CST_LOW (TYPE_SIZE (type)))
     TYPE_MODE (type) = mode;
+  else
+    TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
 
   /* If structure's known alignment is less than what the scalar
      mode would need, and it matters, then stick with BLKmode.  */
@@ -1404,8 +1418,15 @@ finalize_type_size (tree type)
              && TREE_CODE (type) != QUAL_UNION_TYPE
              && TREE_CODE (type) != ARRAY_TYPE)))
     {
-      TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
-      TYPE_USER_ALIGN (type) = 0;
+      unsigned mode_align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+
+      /* Don't override a larger alignment requirement coming from a user
+        alignment of one of the fields.  */
+      if (mode_align >= TYPE_ALIGN (type))
+       {
+         TYPE_ALIGN (type) = mode_align;
+         TYPE_USER_ALIGN (type) = 0;
+       }
     }
 
   /* Do machine-dependent extra alignment.  */
@@ -1613,7 +1634,7 @@ layout_type (tree type)
            enum machine_mode mode;
 
            /* First, look for a supported vector type.  */
-           if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
+           if (SCALAR_FLOAT_MODE_P (innermode))
              mode = MIN_MODE_VECTOR_FLOAT;
            else
              mode = MIN_MODE_VECTOR_INT;
@@ -1795,6 +1816,17 @@ layout_type (tree type)
                TYPE_MODE (type) = BLKmode;
              }
          }
+       /* When the element size is constant, check that it is at least as
+          large as the element alignment.  */
+       if (TYPE_SIZE_UNIT (element)
+           && TREE_CODE (TYPE_SIZE_UNIT (element)) == INTEGER_CST
+           /* If TYPE_SIZE_UNIT overflowed, then it is certainly larger than
+              TYPE_ALIGN_UNIT.  */
+           && !TREE_CONSTANT_OVERFLOW (TYPE_SIZE_UNIT (element))
+           && !integer_zerop (TYPE_SIZE_UNIT (element))
+           && compare_tree_int (TYPE_SIZE_UNIT (element),
+                                TYPE_ALIGN_UNIT (element)) < 0)
+         error ("alignment of array elements is greater than element size");
        break;
       }
 
@@ -1944,8 +1976,10 @@ set_sizetype (tree type)
   TYPE_PRECISION (t) = precision;
   TYPE_UID (t) = TYPE_UID (bitsizetype);
   TYPE_IS_SIZETYPE (t) = 1;
+
   /* Replace our original stub bitsizetype.  */
   memcpy (bitsizetype, t, tree_size (bitsizetype));
+  TYPE_MAIN_VARIANT (bitsizetype) = bitsizetype;
   
   if (TYPE_UNSIGNED (type))
     {