OSDN Git Service

* cp-tree.h (finish_unary_op_expr): New function.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 295e594..ba67ec5 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -27,12 +27,13 @@ Boston, MA 02111-1307, USA.  */
    line numbers.  For example, the CONST_DECLs for enum values.  */
 
 #include "config.h"
+#include "system.h"
 #include "tree.h"
 #include "flags.h"
 #include "output.h"
 #include "c-tree.h"
 #include "c-lex.h"
-#include <stdio.h>
+#include "toplev.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -143,11 +144,13 @@ tree intQI_type_node;
 tree intHI_type_node;
 tree intSI_type_node;
 tree intDI_type_node;
+tree intTI_type_node;
 
 tree unsigned_intQI_type_node;
 tree unsigned_intHI_type_node;
 tree unsigned_intSI_type_node;
 tree unsigned_intDI_type_node;
+tree unsigned_intTI_type_node;
 
 /* a VOID_TYPE node.  */
 
@@ -471,9 +474,14 @@ int explicit_flag_signed_bitfields = 0;
 
 int flag_no_ident = 0;
 
-/* Nonzero means warn about implicit declarations.  */
+/* Nonzero means warn about use of implicit int. */
 
-int warn_implicit;
+int warn_implicit_int;
+
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
+
+int mesg_implicit_function_declaration;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -553,9 +561,14 @@ int warn_missing_braces;
 
 int warn_main;
 
-/* Warn about comparison of signed and unsigned values.  */
+/* Warn about #pragma directives that are not recognised.  */
+
+int warn_unknown_pragmas = 0; /* Tri state variable.  */  
 
-int warn_sign_compare;
+/* Warn about comparison of signed and unsigned values.
+   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
+
+int warn_sign_compare = -1;
 
 /* Nonzero means `$' can be in an identifier.  */
 
@@ -647,10 +660,24 @@ c_decode_option (p)
     flag_no_ident = 0;
   else if (!strcmp (p, "-ansi"))
     flag_no_asm = 1, flag_no_nonansi_builtin = 1;
+  else if (!strcmp (p, "-Werror-implicit-function-declaration"))
+    mesg_implicit_function_declaration = 2;
+  else if (!strcmp (p, "-Wimplicit-function-declaration"))
+    mesg_implicit_function_declaration = 1;
+  else if (!strcmp (p, "-Wno-implicit-function-declaration"))
+    mesg_implicit_function_declaration = 0;
+  else if (!strcmp (p, "-Wimplicit-int"))
+    warn_implicit_int = 1;
+  else if (!strcmp (p, "-Wno-implicit-int"))
+    warn_implicit_int = 0;
   else if (!strcmp (p, "-Wimplicit"))
-    warn_implicit = 1;
+    {
+      warn_implicit_int = 1;
+      if (mesg_implicit_function_declaration != 2)
+        mesg_implicit_function_declaration = 1;
+    }
   else if (!strcmp (p, "-Wno-implicit"))
-    warn_implicit = 0;
+    warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
   else if (!strcmp (p, "-Wwrite-strings"))
     warn_write_strings = 1;
   else if (!strcmp (p, "-Wno-write-strings"))
@@ -743,6 +770,12 @@ c_decode_option (p)
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
     warn_sign_compare = 0;
+  else if (!strcmp (p, "-Wunknown-pragmas"))
+    /* Set to greater than 1, so that even unknown pragmas in system
+       headers will be warned about.  */
+    warn_unknown_pragmas = 2;
+  else if (!strcmp (p, "-Wno-unknown-pragmas"))
+    warn_unknown_pragmas = 0;
   else if (!strcmp (p, "-Wall"))
     {
       /* We save the value of warn_uninitialized, since if they put
@@ -750,7 +783,8 @@ c_decode_option (p)
         warning about not using it without also specifying -O.  */
       if (warn_uninitialized != 1)
        warn_uninitialized = 2;
-      warn_implicit = 1;
+      warn_implicit_int = 1;
+      mesg_implicit_function_declaration = 1;
       warn_return_type = 1;
       warn_unused = 1;
       warn_switch = 1;
@@ -758,10 +792,11 @@ c_decode_option (p)
       warn_char_subscripts = 1;
       warn_parentheses = 1;
       warn_missing_braces = 1;
-      warn_sign_compare = 1;
       /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
         it off only if it's not explicit.  */
       warn_main = 2;
+      /* Only warn about unknown pragmas that are not in system headers.  */
+      warn_unknown_pragmas = 1;
     }
   else
     return 0;
@@ -1386,7 +1421,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   char *errmsg = 0;
 
   if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
-    DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
+    DECL_MACHINE_ATTRIBUTES (newdecl)
+      =  merge_machine_decl_attributes (olddecl, newdecl);
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1738,7 +1774,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
   /* Optionally warn about more than one declaration for the same name.  */
   if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
-      /* Dont warn about a function declaration
+      /* Don't warn about a function declaration
         followed by a definition.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
           && DECL_INITIAL (olddecl) == 0)
@@ -1948,13 +1984,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     }
   if (different_binding_level)
     {
-      /* Don't output a duplicate symbol for this declaration.  */
-      TREE_ASM_WRITTEN (newdecl) = 1;
+      /* Don't output a duplicate symbol or debugging information for this
+        declaration.  */
+      TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
       return 0;
     }
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDdECL's DECL_UID.  */
+     But preserve OLDDECL's DECL_UID.  */
   {
     register unsigned olddecl_uid = DECL_UID (olddecl);
 
@@ -1964,6 +2001,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     DECL_UID (olddecl) = olddecl_uid;
   }
 
+  /* NEWDECL contains the merged attribute lists.
+     Update OLDDECL to be the same.  */
+  DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+
   return 1;
 }
 
@@ -2048,6 +2089,7 @@ pushdecl (x)
             DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
             "previous declaration of `%s'",
             IDENTIFIER_POINTER (name));
+         TREE_THIS_VOLATILE (name) = 1;
        }
 
       if (t != 0 && duplicate_decls (x, t, different_binding_level))
@@ -2081,7 +2123,7 @@ pushdecl (x)
                MY_TYPE object;
 
         Later parts of the compiler might only know that `object' was of
-        type `struct S' if if were not for code just below.  With this
+        type `struct S' if it were not for code just below.  With this
         code however, later parts of the compiler see something like:
 
                struct S' == struct S
@@ -2112,7 +2154,8 @@ pushdecl (x)
              if (TYPE_NAME (TREE_TYPE (x)) == 0)
                TYPE_NAME (TREE_TYPE (x)) = x;
             }
-          else if (TREE_TYPE (x) != error_mark_node)
+          else if (TREE_TYPE (x) != error_mark_node
+                  && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
             {
               tree tt = TREE_TYPE (x);
              DECL_ORIGINAL_TYPE (x) = tt;
@@ -2250,8 +2293,11 @@ pushdecl (x)
              else if (TREE_CODE (x) == TYPE_DECL)
                ;
              else if (IDENTIFIER_IMPLICIT_DECL (name))
-               pedwarn ("`%s' was declared implicitly `extern' and later `static'",
-                        IDENTIFIER_POINTER (name));
+               {
+                 if (! TREE_THIS_VOLATILE (name))
+                   pedwarn ("`%s' was declared implicitly `extern' and later `static'",
+                            IDENTIFIER_POINTER (name));
+               }
              else
                pedwarn ("`%s' was declared `extern' and later `static'",
                         IDENTIFIER_POINTER (name));
@@ -2467,9 +2513,15 @@ implicitly_declare (functionid)
 
   rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
 
-  if (warn_implicit && implicit_warning)
-    warning ("implicit declaration of function `%s'",
-            IDENTIFIER_POINTER (functionid));
+  if (mesg_implicit_function_declaration && implicit_warning)
+    {
+      if (mesg_implicit_function_declaration == 2)
+        error ("implicit declaration of function `%s'",
+                 IDENTIFIER_POINTER (functionid));
+      else
+        warning ("implicit declaration of function `%s'",
+                 IDENTIFIER_POINTER (functionid));
+    }
   else if (warn_traditional && traditional_warning)
     warning ("function `%s' was previously declared within a block",
             IDENTIFIER_POINTER (functionid));
@@ -2849,7 +2901,7 @@ init_decl_processing ()
   tree traditional_ptr_type_node;
   /* Data types of memcpy and strlen.  */
   tree memcpy_ftype, memset_ftype, strlen_ftype;
-  tree void_ftype_any;
+  tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree temp;
   tree array_domain_type;
@@ -2908,25 +2960,15 @@ init_decl_processing ()
   /* `unsigned long' is the standard type for sizeof.
      Traditionally, use a signed type.
      Note that stddef.h uses `unsigned long',
-     and this must agree, even of long and int are the same size.  */
-  sizetype
-    = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+     and this must agree, even if long and int are the same size.  */
+  set_sizetype
+    (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
   if (flag_traditional && TREE_UNSIGNED (sizetype))
-    sizetype = signed_type (sizetype);
+    set_sizetype (signed_type (sizetype));
 
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
 
-  TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (short_integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (short_unsigned_type_node)) = sizetype;
-
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
@@ -2951,6 +2993,9 @@ init_decl_processing ()
   intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
 
+  intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
 
@@ -2963,6 +3008,9 @@ init_decl_processing ()
   unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
 
+  unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
   pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT],
@@ -3165,6 +3213,11 @@ init_decl_processing ()
                                                            sizetype,
                                                            endlink))));
 
+  ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+  ptr_ftype_ptr
+    = build_function_type (ptr_type_node,
+                          tree_cons (NULL_TREE, ptr_type_node, endlink));
+
   builtin_function ("__builtin_constant_p", default_function_type,
                    BUILT_IN_CONSTANT_P, NULL_PTR);
 
@@ -3186,6 +3239,38 @@ init_decl_processing ()
                    build_function_type (ptr_type_node, NULL_TREE),
                    BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
 
+  /* Hooks for the DWARF 2 __throw routine.  */
+  builtin_function ("__builtin_unwind_init",
+                   build_function_type (void_type_node, endlink),
+                   BUILT_IN_UNWIND_INIT, NULL_PTR);
+  builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
+  builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+  builtin_function ("__builtin_dwarf_fp_regnum",
+                   build_function_type (unsigned_type_node, endlink),
+                   BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
+  builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
+                   BUILT_IN_DWARF_REG_SIZE, NULL_PTR);             
+  builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_set_return_addr_reg",
+                   build_function_type (void_type_node, 
+                                        tree_cons (NULL_TREE,
+                                                   ptr_type_node,
+                                                   endlink)),
+                   BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
+  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
+                   BUILT_IN_EH_STUB, NULL_PTR);
+  builtin_function
+    ("__builtin_set_eh_regs",
+     build_function_type (void_type_node,
+                         tree_cons (NULL_TREE, ptr_type_node,
+                                    tree_cons (NULL_TREE,
+                                               type_for_mode (ptr_mode, 0),
+                                               endlink))),
+     BUILT_IN_SET_EH_REGS, NULL_PTR);
+
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
                                         tree_cons (NULL_TREE,
@@ -3278,7 +3363,7 @@ init_decl_processing ()
   builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
                    BUILT_IN_MEMCMP, "memcmp");
   builtin_function ("__builtin_memset", memset_ftype,
-                   BUILT_IN_MEMSET, NULL_PTR);
+                   BUILT_IN_MEMSET, "memset");
   builtin_function ("__builtin_strcmp", int_ftype_string_string,
                    BUILT_IN_STRCMP, "strcmp");
   builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
@@ -3375,8 +3460,6 @@ init_decl_processing ()
                    BUILT_IN_FMOD, NULL_PTR);
   builtin_function ("__builtin_frem", double_ftype_double_double,
                    BUILT_IN_FREM, NULL_PTR);
-  builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int,
-                   BUILT_IN_MEMSET, NULL_PTR);
   builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
                    NULL_PTR);
   builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
@@ -3462,9 +3545,14 @@ shadow_tag_warned (declspecs, warned)
 {
   int found_tag = 0;
   register tree link;
+  tree specs, attrs;
 
   pending_invalid_xref = 0;
 
+  /* Remove the attributes from declspecs, since they will confuse the
+     following code.  */
+  split_specs_attrs (declspecs, &specs, &attrs);
+
   for (link = declspecs; link; link = TREE_CHAIN (link))
     {
       register tree value = TREE_VALUE (link);
@@ -3825,7 +3913,7 @@ finish_decl (decl, init, asmspec_tree)
                 declaration into a file scope one.  This can be detected
                 by TREE_ASM_WRITTEN being set.  */
                (DECL_INITIAL (decl) != 0
-                || DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl))
+                || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl)))
              :
                /* An automatic variable with an incomplete type
                   is an error.  */
@@ -3843,6 +3931,9 @@ finish_decl (decl, init, asmspec_tree)
          else
            error_with_decl (decl, "storage size of `%s' isn't constant");
        }
+
+      if (TREE_USED  (type))
+       TREE_USED (decl) = 1;
     }
 
   /* If this is a function and an assembler name is specified, it isn't
@@ -4316,17 +4407,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   if (type == 0)
     {
-      if (! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                        | (1 << (int) RID_SIGNED)
-                        | (1 << (int) RID_UNSIGNED))))
+      if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+                         | (1 << (int) RID_SIGNED)
+                         | (1 << (int) RID_UNSIGNED))))
+         && ! (in_system_header && ! allocation_temporary_p ()))
        {
          /* C9x will probably require a diagnostic here.
             For now, issue a warning if -Wreturn-type and this is a function,
             or if -Wimplicit; prefer the former warning since it is more
             explicit.  */
-         if ((warn_implicit || warn_return_type) && funcdef_flag)
+         if ((warn_implicit_int || warn_return_type) && funcdef_flag)
            warn_about_return_type = 1;
-         else if (warn_implicit)
+         else if (warn_implicit_int)
            warning ("type defaults to `int' in declaration of `%s'", name);
        }
 
@@ -4339,7 +4431,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   /* Long double is a special combination.  */
 
-  if ((specbits & 1 << (int) RID_LONG)
+  if ((specbits & 1 << (int) RID_LONG) && ! longlong
       && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
       specbits &= ~ (1 << (int) RID_LONG);
@@ -4353,11 +4445,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       int ok = 0;
 
-      if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for `%s'", name);
-      else if ((specbits & 1 << (int) RID_LONG)
-              && (specbits & 1 << (int) RID_SHORT))
-       error ("long and short specified together for `%s'", name);
+      if ((specbits & 1 << (int) RID_LONG)
+         && (specbits & 1 << (int) RID_SHORT))
+       error ("both long and short specified for `%s'", name);
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && explicit_char)
@@ -4365,10 +4455,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && TREE_CODE (type) == REAL_TYPE)
-       error ("long or short specified with floating type for `%s'", name);
+       {
+         static int already = 0;
+
+         error ("long or short specified with floating type for `%s'", name);
+         if (! already && ! pedantic)
+           {
+             error ("the only valid combination is `long double'");
+             already = 1;
+           }
+       }
       else if ((specbits & 1 << (int) RID_SIGNED)
               && (specbits & 1 << (int) RID_UNSIGNED))
-       error ("signed and unsigned given together for `%s'", name);
+       error ("both signed and unsigned specified for `%s'", name);
+      else if (TREE_CODE (type) != INTEGER_TYPE)
+       error ("long, short, signed or unsigned invalid for `%s'", name);
       else
        {
          ok = 1;
@@ -4663,6 +4764,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                   convert (index_type, size),
                                   convert (index_type, size_one_node)));
 
+             /* If that overflowed, the array is too big.
+                ??? While a size of INT_MAX+1 technically shouldn't cause
+                an overflow (because we subtract 1), the overflow is recorded
+                during the conversion to index_type, before the subtraction.
+                Handling this case seems like an unnecessary complication.  */
+             if (TREE_OVERFLOW (itype))
+               {
+                 error ("size of array `%s' is too large", name);
+                 type = error_mark_node;
+                 continue;
+               }
+
              if (size_varies)
                itype = variable_size (itype);
              itype = build_index_type (itype);
@@ -4781,7 +4894,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          {
            register tree link;
 
-           for (link = current_function_parm_tags;
+           for (link = last_function_parm_tags;
                 link;
                 link = TREE_CHAIN (link))
              TYPE_CONTEXT (TREE_VALUE (link)) = type;
@@ -4838,6 +4951,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   /* Now TYPE has the actual type.  */
 
+  /* Did array size calculations overflow?  */
+
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_SIZE (type)
+      && TREE_OVERFLOW (TYPE_SIZE (type)))
+    error ("size of array `%s' is too large", name);
+
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
 
   if (specbits & (1 << (int) RID_TYPEDEF))
@@ -5058,9 +5178,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
            if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
              warning ("cannot inline function `main'");
-           else if (last && (TYPE_MAIN_VARIANT (TREE_VALUE (last))
-                             != void_type_node))
-             warning ("inline declaration ignored for function with `...'");
            else
              /* Assume that otherwise the function can be inlined.  */
              DECL_INLINE (decl) = 1;
@@ -5380,7 +5497,7 @@ parmlist_tags_warning ()
       enum tree_code code = TREE_CODE (TREE_VALUE (elt));
       /* An anonymous union parm type is meaningful as a GNU extension.
         So don't warn for that.  */
-      if (code == UNION_TYPE && !pedantic)
+      if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
        continue;
       if (TREE_PURPOSE (elt) != 0)
        warning ("`%s %s' declared inside parameter list",
@@ -5483,6 +5600,7 @@ start_struct (code, name)
   if (ref && TREE_CODE (ref) == code)
     {
       C_TYPE_BEING_DEFINED (ref) = 1;
+      TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
        error ((code == UNION_TYPE ? "redefinition of `union %s'"
                : "redefinition of `struct %s'"),
@@ -5724,7 +5842,7 @@ finish_struct (t, fieldlist, attributes)
        }
       else if (TREE_TYPE (x) != error_mark_node)
        {
-         int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
+         unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
                           : TYPE_ALIGN (TREE_TYPE (x)));
          /* Non-bit-fields are aligned for their type, except packed
             fields which require only BITS_PER_UNIT alignment.  */
@@ -6164,7 +6282,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == 0)
-    return 0;
+    {
+      immediate_size_expand = old_immediate_size_expand;
+      return 0;
+    }
 
   decl_attributes (decl1, prefix_attributes, attributes);