OSDN Git Service

Emit an error for too large arrays instead of an ICE.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index d516ffe..a1fdce7 100644 (file)
@@ -60,6 +60,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "libfuncs.h"
 #include "except.h"
 #include "langhooks-def.h"
+#include "pointer-set.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -465,7 +466,7 @@ c_print_identifier (FILE *file, tree node, int indent)
     {
       tree rid = ridpointers[C_RID_CODE (node)];
       indent_to (file, indent + 4);
-      fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
+      fprintf (file, "rid %p \"%s\"",
               (void *) rid, IDENTIFIER_POINTER (rid));
     }
 }
@@ -1308,7 +1309,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          if (DECL_INITIAL (olddecl))
            {
              /* If both decls are in the same TU and the new declaration
-                isn't overridding an extern inline reject the new decl.
+                isn't overriding an extern inline reject the new decl.
                 When we handle c99 style inline rules we'll want to reject
                 the following:
 
@@ -1471,7 +1472,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   /* warnings */
   /* All decls must agree on a visibility.  */
-  if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS) 
+      && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
       warning (0, "redeclaration of %q+D with different visibility "
@@ -1638,8 +1640,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          }
     }
 
-  /* Keep the old rtl since we can safely use it.  */
-  COPY_DECL_RTL (olddecl, newdecl);
 
   /* Merge the type qualifiers.  */
   if (TREE_READONLY (newdecl))
@@ -1664,163 +1664,188 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
     DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
 
-  /* Merge the unused-warning information.  */
-  if (DECL_IN_SYSTEM_HEADER (olddecl))
-    DECL_IN_SYSTEM_HEADER (newdecl) = 1;
-  else if (DECL_IN_SYSTEM_HEADER (newdecl))
-    DECL_IN_SYSTEM_HEADER (olddecl) = 1;
-
   /* Merge the initialization information.  */
    if (DECL_INITIAL (newdecl) == 0)
     DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
 
-  /* Merge the section attribute.
-     We want to issue an error if the sections conflict but that must be
-     done later in decl_attributes since we are called before attributes
-     are assigned.  */
-  if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
-    DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
-
-  /* Copy the assembler name.
-     Currently, it can only be defined in the prototype.  */
-  COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
-
-  /* Use visibility of whichever declaration had it specified */
-  if (DECL_VISIBILITY_SPECIFIED (olddecl))
-    {
-      DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
-      DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
-    }
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
-      DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
-      DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
-      DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
-       |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
-      TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-      TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
-      DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
-      DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
-      DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
-    }
-
-  /* Merge the storage class information.  */
-  merge_weak (newdecl, olddecl);
-
-  /* For functions, static overrides non-static.  */
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
-      /* This is since we don't automatically
-        copy the attributes of NEWDECL into OLDDECL.  */
-      TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
-      /* If this clears `static', clear it in the identifier too.  */
-      if (!TREE_PUBLIC (olddecl))
-       TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
-    }
-  if (DECL_EXTERNAL (newdecl))
-    {
-      TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
-      DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
-
-      /* An extern decl does not override previous storage class.  */
-      TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
-      if (!DECL_EXTERNAL (newdecl))
-       {
-         DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
-         DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
-       }
-    }
-  else
-    {
-      TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
-      TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
-    }
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* If we're redefining a function previously defined as extern
-        inline, make sure we emit debug info for the inline before we
-        throw it away, in case it was inlined into a function that hasn't
-        been written out yet.  */
-      if (new_is_definition && DECL_INITIAL (olddecl))
-       {
-         if (TREE_USED (olddecl)
-             /* In unit-at-a-time mode we never inline re-defined extern
-                inline functions.  */
-             && !flag_unit_at_a_time
-             && cgraph_function_possibly_inlined_p (olddecl))
-           (*debug_hooks->outlining_inline_function) (olddecl);
-
-         /* The new defn must not be inline.  */
-         DECL_INLINE (newdecl) = 0;
-         DECL_UNINLINABLE (newdecl) = 1;
-       }
-      else
-       {
-         /* If either decl says `inline', this fn is inline,
-            unless its definition was passed already.  */
-         if (DECL_DECLARED_INLINE_P (newdecl)
-             || DECL_DECLARED_INLINE_P (olddecl))
-           DECL_DECLARED_INLINE_P (newdecl) = 1;
-
-         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
-           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
-       }
+   if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
+     {
+       /* Merge the unused-warning information.  */
+       if (DECL_IN_SYSTEM_HEADER (olddecl))
+        DECL_IN_SYSTEM_HEADER (newdecl) = 1;
+       else if (DECL_IN_SYSTEM_HEADER (newdecl))
+        DECL_IN_SYSTEM_HEADER (olddecl) = 1;
+
+       /* Merge the section attribute.
+         We want to issue an error if the sections conflict but that must be
+         done later in decl_attributes since we are called before attributes
+         are assigned.  */
+       if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+        DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+       
+       /* Copy the assembler name.
+         Currently, it can only be defined in the prototype.  */
+       COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
+
+       /* Use visibility of whichever declaration had it specified */
+       if (DECL_VISIBILITY_SPECIFIED (olddecl))
+        {
+          DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+          DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+        }
+       
+       if (TREE_CODE (newdecl) == FUNCTION_DECL)
+        {
+          DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
+          DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+          DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+          TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+          TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+          DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+          DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+          DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
+        }
+       
+       /* Merge the storage class information.  */
+       merge_weak (newdecl, olddecl);
 
-      if (DECL_BUILT_IN (olddecl))
-       {
-         /* If redeclaring a builtin function, it stays built in.
-            But it gets tagged as having been declared.  */
-         DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
-         DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
-         C_DECL_DECLARED_BUILTIN (newdecl) = 1;
-         if (new_is_prototype)
-           C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
-         else
-           C_DECL_BUILTIN_PROTOTYPE (newdecl)
-             = C_DECL_BUILTIN_PROTOTYPE (olddecl);
-       }
+       /* For functions, static overrides non-static.  */
+       if (TREE_CODE (newdecl) == FUNCTION_DECL)
+        {
+          TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
+          /* This is since we don't automatically
+             copy the attributes of NEWDECL into OLDDECL.  */
+          TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+          /* If this clears `static', clear it in the identifier too.  */
+          if (!TREE_PUBLIC (olddecl))
+            TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
+        }
+     }
+   
+   if (DECL_EXTERNAL (newdecl))
+     {
+       TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+       DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+
+       /* An extern decl does not override previous storage class.  */
+       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
+       if (!DECL_EXTERNAL (newdecl))
+        {
+          DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+          DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
+        }
+     }
+   else
+     {
+       TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
+       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+     }
+   
+   if (TREE_CODE (newdecl) == FUNCTION_DECL) 
+     {
+       /* If we're redefining a function previously defined as extern
+         inline, make sure we emit debug info for the inline before we
+         throw it away, in case it was inlined into a function that hasn't
+         been written out yet.  */
+       if (new_is_definition && DECL_INITIAL (olddecl))
+        {
+          if (TREE_USED (olddecl)
+              /* In unit-at-a-time mode we never inline re-defined extern
+                 inline functions.  */
+              && !flag_unit_at_a_time
+              && cgraph_function_possibly_inlined_p (olddecl))
+            (*debug_hooks->outlining_inline_function) (olddecl);
+
+          /* The new defn must not be inline.  */
+          DECL_INLINE (newdecl) = 0;
+          DECL_UNINLINABLE (newdecl) = 1;
+        }
+       else
+        {
+          /* If either decl says `inline', this fn is inline,
+             unless its definition was passed already.  */
+          if (DECL_DECLARED_INLINE_P (newdecl)
+              || DECL_DECLARED_INLINE_P (olddecl))
+            DECL_DECLARED_INLINE_P (newdecl) = 1;
+
+          DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+            = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+        }
 
-      /* Also preserve various other info from the definition.  */
-      if (!new_is_definition)
-       {
-         DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
-         DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
-         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
-         DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-
-         /* Set DECL_INLINE on the declaration if we've got a body
-            from which to instantiate.  */
-         if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
-           {
-             DECL_INLINE (newdecl) = 1;
-             DECL_ABSTRACT_ORIGIN (newdecl)
-               = DECL_ABSTRACT_ORIGIN (olddecl);
-           }
-       }
-      else
-       {
-         /* If a previous declaration said inline, mark the
-            definition as inlinable.  */
-         if (DECL_DECLARED_INLINE_P (newdecl)
-             && !DECL_UNINLINABLE (newdecl))
-           DECL_INLINE (newdecl) = 1;
-       }
-    }
+       if (DECL_BUILT_IN (olddecl))
+        {
+          /* If redeclaring a builtin function, it stays built in.
+             But it gets tagged as having been declared.  */
+          DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+          DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+          C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+          if (new_is_prototype)
+            C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+          else
+            C_DECL_BUILTIN_PROTOTYPE (newdecl)
+              = C_DECL_BUILTIN_PROTOTYPE (olddecl);
+        }
 
-  /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
+       /* Also preserve various other info from the definition.  */
+       if (!new_is_definition)
+        {
+          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
+          DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+          DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
+          DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+
+          /* Set DECL_INLINE on the declaration if we've got a body
+             from which to instantiate.  */
+          if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
+            {
+              DECL_INLINE (newdecl) = 1;
+              DECL_ABSTRACT_ORIGIN (newdecl)
+                = DECL_ABSTRACT_ORIGIN (olddecl);
+            }
+        }
+       else
+        {
+          /* If a previous declaration said inline, mark the
+             definition as inlinable.  */
+          if (DECL_DECLARED_INLINE_P (newdecl)
+              && !DECL_UNINLINABLE (newdecl))
+            DECL_INLINE (newdecl) = 1;
+        }
+     }
+   
+   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
   {
     unsigned olddecl_uid = DECL_UID (olddecl);
     tree olddecl_context = DECL_CONTEXT (olddecl);
-
+    
     memcpy ((char *) olddecl + sizeof (struct tree_common),
            (char *) newdecl + sizeof (struct tree_common),
-           sizeof (struct tree_decl) - sizeof (struct tree_common));
+           sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+    switch (TREE_CODE (olddecl))
+      {
+      case FIELD_DECL:
+      case VAR_DECL:
+      case PARM_DECL:
+      case LABEL_DECL:
+      case RESULT_DECL:
+      case CONST_DECL:
+      case TYPE_DECL:
+      case FUNCTION_DECL:
+       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+               (char *) newdecl + sizeof (struct tree_decl_common),
+               tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
+       break;
+
+      default:
+       
+       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+               (char *) newdecl + sizeof (struct tree_decl_common),
+               sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common));
+      }
     DECL_UID (olddecl) = olddecl_uid;
     DECL_CONTEXT (olddecl) = olddecl_context;
   }
@@ -1866,13 +1891,7 @@ warn_if_shadowing (tree new_decl)
       /* No shadow warnings for internally generated vars.  */
       || DECL_IS_BUILTIN (new_decl)
       /* No shadow warnings for vars made for inlining.  */
-      || DECL_FROM_INLINE (new_decl)
-      /* Don't warn about the parm names in function declarator
-        within a function declarator.  It would be nice to avoid
-        warning in any function declarator in a declaration, as
-        opposed to a definition, but there is no way to tell
-        it's not a definition at this point.  */
-      || (TREE_CODE (new_decl) == PARM_DECL && current_scope->outer->parm_flag))
+      || DECL_FROM_INLINE (new_decl))
     return;
 
   /* Is anything being shadowed?  Invisible decls do not count.  */
@@ -1883,27 +1902,28 @@ warn_if_shadowing (tree new_decl)
 
        if (old_decl == error_mark_node)
          {
-           warning (0, "declaration of %q+D shadows previous non-variable",
-                    new_decl);
+           warning (OPT_Wshadow, "declaration of %q+D shadows previous "
+                    "non-variable", new_decl);
            break;
          }
        else if (TREE_CODE (old_decl) == PARM_DECL)
-         warning (0, "declaration of %q+D shadows a parameter", new_decl);
-       else if (DECL_FILE_SCOPE_P (old_decl))
-         warning (0, "declaration of %q+D shadows a global declaration",
+         warning (OPT_Wshadow, "declaration of %q+D shadows a parameter",
                   new_decl);
+       else if (DECL_FILE_SCOPE_P (old_decl))
+         warning (OPT_Wshadow, "declaration of %q+D shadows a global "
+                  "declaration", new_decl);
        else if (TREE_CODE (old_decl) == FUNCTION_DECL
                 && DECL_BUILT_IN (old_decl))
          {
-           warning (0, "declaration of %q+D shadows a built-in function",
-                    new_decl);
+           warning (OPT_Wshadow, "declaration of %q+D shadows "
+                    "a built-in function", new_decl);
            break;
          }
        else
-         warning (0, "declaration of %q+D shadows a previous local",
+         warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
                   new_decl);
 
-       warning (0, "%Jshadowed declaration is here", old_decl);
+       warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl);
 
        break;
       }
@@ -2195,7 +2215,8 @@ pushdecl (tree x)
        }
     }
 
-  warn_if_shadowing (x);
+  if (TREE_CODE (x) != PARM_DECL)
+    warn_if_shadowing (x);
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
@@ -3749,6 +3770,30 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
        warning (0, "%qs is narrower than values of its type", name);
     }
 }
+
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
+static tree
+c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+{
+  /* Extended integer types of the same width as a standard type have
+     lesser rank, so those of the same width as int promote to int or
+     unsigned int and are valid for printf formats expecting int or
+     unsigned int.  To avoid such special cases, avoid creating
+     extended integer types for bit-fields if a standard integer type
+     is available.  */
+  if (width == TYPE_PRECISION (integer_type_node))
+    return unsignedp ? unsigned_type_node : integer_type_node;
+  if (width == TYPE_PRECISION (signed_char_type_node))
+    return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+  if (width == TYPE_PRECISION (short_integer_type_node))
+    return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+  if (width == TYPE_PRECISION (long_integer_type_node))
+    return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+  if (width == TYPE_PRECISION (long_long_integer_type_node))
+    return (unsignedp ? long_long_unsigned_type_node
+           : long_long_integer_type_node);
+  return build_nonstandard_integer_type (width, unsignedp);
+}
 \f
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
@@ -4339,7 +4384,7 @@ grokdeclarator (const struct c_declarator *declarator,
   if (TREE_CODE (type) == ARRAY_TYPE
       && COMPLETE_TYPE_P (type)
       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
-      && TREE_OVERFLOW (TYPE_SIZE (type)))
+      && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
     {
       error ("size of array %qs is too large", name);
       /* If we proceed with the array type as it is, we'll eventually
@@ -4475,7 +4520,6 @@ grokdeclarator (const struct c_declarator *declarator,
          promoted_type = c_type_promotes_to (type);
 
        DECL_ARG_TYPE (decl) = promoted_type;
-       DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
        if (declspecs->inline_p)
          pedwarn ("parameter %q+D declared %<inline%>", decl);
       }
@@ -4680,8 +4724,11 @@ grokdeclarator (const struct c_declarator *declarator,
 
     /* If a type has volatile components, it should be stored in memory.
        Otherwise, the fact that those components are volatile
-       will be ignored, and would even crash the compiler.  */
-    if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
+       will be ignored, and would even crash the compiler.
+       Of course, this only makes sense on  VAR,PARM, and RESULT decl's.   */
+    if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))
+       && (TREE_CODE (decl) == VAR_DECL ||  TREE_CODE (decl) == PARM_DECL
+         || TREE_CODE (decl) == RESULT_DECL))
       {
        /* It is not an error for a structure with volatile fields to
           be declared register, but reset DECL_REGISTER since it
@@ -4784,6 +4831,9 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
                             parm, parmno);
                }
            }
+
+         if (DECL_NAME (parm) && TREE_USED (parm))
+           warn_if_shadowing (parm);
        }
       return arg_types;
     }
@@ -5349,7 +5399,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          if (width != TYPE_PRECISION (type))
            {
              TREE_TYPE (*fieldlistp)
-               = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+               = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
              DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
            }
          DECL_INITIAL (*fieldlistp) = 0;
@@ -5420,6 +5470,9 @@ finish_struct (tree t, tree fieldlist, tree attributes)
       TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
       TYPE_ALIGN (x) = TYPE_ALIGN (t);
       TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
+      C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
+      C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
+      C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
     }
 
   /* If this was supposed to be a transparent union, but we can't
@@ -6051,8 +6104,12 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
-       bind (DECL_NAME (decl), decl, current_scope,
-             /*invisible=*/false, /*nested=*/false);
+       {
+         bind (DECL_NAME (decl), decl, current_scope,
+               /*invisible=*/false, /*nested=*/false);
+         if (!TREE_USED (decl))
+           warn_if_shadowing (decl);
+       }
       else
        error ("%Jparameter name omitted", decl);
     }
@@ -6085,13 +6142,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
   struct c_binding *b;
   tree parm, decl, last;
   tree parmids = arg_info->parms;
-
-  /* We use DECL_WEAK as a flag to show which parameters have been
-     seen already, since it is not used on PARM_DECL.  */
-#ifdef ENABLE_CHECKING
-  for (b = current_scope->bindings; b; b = b->prev)
-    gcc_assert (TREE_CODE (b->decl) != PARM_DECL || !DECL_WEAK (b->decl));
-#endif
+  struct pointer_set_t *seen_args = pointer_set_create ();
 
   if (!in_system_header)
     warning (OPT_Wold_style_definition, "%Jold-style function definition",
@@ -6117,7 +6168,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
            error ("%q+D declared as a non-parameter", decl);
          /* If the declaration is already marked, we have a duplicate
             name.  Complain and ignore the duplicate.  */
-         else if (DECL_WEAK (decl))
+         else if (pointer_set_contains (seen_args, decl))
            {
              error ("multiple parameters named %q+D", decl);
              TREE_PURPOSE (parm) = 0;
@@ -6132,6 +6183,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
              DECL_ARG_TYPE (decl) = integer_type_node;
              layout_decl (decl, 0);
            }
+         warn_if_shadowing (decl);
        }
       /* If no declaration found, default to int.  */
       else
@@ -6140,6 +6192,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
          DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
          DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (fndecl);
          pushdecl (decl);
+         warn_if_shadowing (decl);
 
          if (flag_isoc99)
            pedwarn ("type of %q+D defaults to %<int%>", decl);
@@ -6148,7 +6201,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
        }
 
       TREE_PURPOSE (parm) = decl;
-      DECL_WEAK (decl) = 1;
+      pointer_set_insert (seen_args, decl);
     }
 
   /* Now examine the parms chain for incomplete declarations
@@ -6167,7 +6220,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
          TREE_TYPE (parm) = error_mark_node;
        }
 
-      if (!DECL_WEAK (parm))
+      if (!pointer_set_contains (seen_args, parm))
        {
          error ("declaration for parameter %q+D but no such parameter", parm);
 
@@ -6190,18 +6243,18 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
     {
       last = TREE_PURPOSE (parm);
       DECL_ARGUMENTS (fndecl) = last;
-      DECL_WEAK (last) = 0;
 
       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
        if (TREE_PURPOSE (parm))
          {
            TREE_CHAIN (last) = TREE_PURPOSE (parm);
            last = TREE_PURPOSE (parm);
-           DECL_WEAK (last) = 0;
          }
       TREE_CHAIN (last) = 0;
     }
 
+  pointer_set_destroy (seen_args);
+
   /* If there was a previous prototype,
      set the DECL_ARG_TYPE of each argument according to
      the type previously specified, and report any mismatches.  */