OSDN Git Service

* Make-lang.in (java/java-tree-inline.o): Removed.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index df61736..6673927 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "input.h"
 #include "tm.h"
 #include "intl.h"
 #include "tree.h"
@@ -634,7 +635,7 @@ push_scope (void)
       if (current_scope && scope->depth == 0)
        {
          scope->depth--;
-         sorry ("GCC supports only %u nested scopes\n", scope->depth);
+         sorry ("GCC supports only %u nested scopes", scope->depth);
        }
 
       current_scope        = scope;
@@ -767,10 +768,8 @@ pop_scope (void)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
              && !DECL_ARTIFICIAL (p)
-             && (scope != file_scope
-                 || (TREE_STATIC (p) && !TREE_PUBLIC (p)
-                     && !TREE_THIS_VOLATILE (p)))
-             && scope != external_scope)
+             && scope != file_scope
+             && scope != external_scope) 
            warning ("%Junused variable %qD", p, p);
 
          if (b->inner_comp)
@@ -898,6 +897,8 @@ pop_file_scope (void)
   /* Pop off the file scope and close this translation unit.  */
   pop_scope ();
   file_scope = 0;
+
+  maybe_apply_pending_pragma_weaks ();
   cgraph_finalize_compilation_unit ();
 }
 
@@ -1007,14 +1008,14 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
       if (TREE_CHAIN (t) == 0
          && TYPE_MAIN_VARIANT (type) != void_type_node)
        {
-         inform ("a parameter list with an ellipsis can't match "
+         inform ("a parameter list with an ellipsis can%'t match "
                  "an empty parameter name list declaration");
          break;
        }
 
       if (c_type_promotes_to (type) != type)
        {
-         inform ("an argument type that has a default promotion can't match "
+         inform ("an argument type that has a default promotion can%'t match "
                  "an empty parameter name list declaration");
          break;
        }
@@ -1065,7 +1066,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
         for the arg.  */
       else if (!comptypes (oldargtype, newargtype))
        {
-         error ("%Jprototype for %qD declares arg %d with incompatible type",
+         error ("%Jprototype for %qD declares argument %d"
+                " with incompatible type",
                 newdecl, newdecl, i);
          return false;
        }
@@ -1114,6 +1116,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   tree newtype, oldtype;
   bool pedwarned = false;
   bool warned = false;
+  bool retval = true;
 
   /* If we have error_mark_node for either decl or type, just discard
      the previous decl - we're in an error cascade already.  */
@@ -1192,7 +1195,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
               && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
               && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
-              && C_FUNCTION_IMPLICIT_INT (newdecl))
+              && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
        {
          pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
          /* Make sure we keep void as the return type.  */
@@ -1200,6 +1203,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
          pedwarned = true;
        }
+      /* Permit void foo (...) to match an earlier call to foo (...) with
+        no declared type (thus, implicitly int).  */
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL
+              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
+              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
+              && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
+       {
+         pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
+         /* Make sure we keep void as the return type.  */
+         TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
+         pedwarned = true;
+       }
       else
        {
          if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
@@ -1252,17 +1267,47 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       if (DECL_INITIAL (newdecl))
        {
-         if (DECL_INITIAL (olddecl)
-             && !(DECL_DECLARED_INLINE_P (olddecl)
-                  && DECL_EXTERNAL (olddecl)
-                  && !(DECL_DECLARED_INLINE_P (newdecl)
-                       && DECL_EXTERNAL (newdecl)
-                       && same_translation_unit_p (olddecl, newdecl))))
+         if (DECL_INITIAL (olddecl))
            {
-             error ("%Jredefinition of %qD", newdecl, newdecl);
-             locate_old_decl (olddecl, error);
-             return false;
-           }
+             /* If both decls have extern inline and are in the same TU,
+                reject the new decl.  */
+             if (DECL_DECLARED_INLINE_P (olddecl)
+                 && DECL_EXTERNAL (olddecl)
+                 && DECL_DECLARED_INLINE_P (newdecl)
+                 && DECL_EXTERNAL (newdecl)
+                 && same_translation_unit_p (newdecl, olddecl))
+               {
+                 error ("%Jredefinition of %qD", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             /* If both decls have not extern inline, reject the new decl.  */
+             if (!DECL_DECLARED_INLINE_P (olddecl)
+                 && !DECL_EXTERNAL (olddecl)
+                 && !DECL_DECLARED_INLINE_P (newdecl)
+                 && !DECL_EXTERNAL (newdecl))
+               {
+                 error ("%Jredefinition of %qD", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             /* If the new decl is declared as extern inline, error if they are
+                in the same TU, otherwise retain the old decl.  */
+             if (!DECL_DECLARED_INLINE_P (olddecl)
+                 && !DECL_EXTERNAL (olddecl)
+                 && DECL_DECLARED_INLINE_P (newdecl)
+                 && DECL_EXTERNAL (newdecl))
+               {
+                 if (same_translation_unit_p (newdecl, olddecl))
+                   {
+                     error ("%Jredefinition of %qD", newdecl, newdecl);
+                     locate_old_decl (olddecl, error);
+                     return false;
+                   }
+                 else
+                   retval = false;
+               }
+          }
        }
       /* If we have a prototype after an old-style function definition,
         the argument types must be checked specially.  */
@@ -1504,7 +1549,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (warned || pedwarned)
     locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
 
-  return true;
+  return retval;
 }
 
 /* Subroutine of duplicate_decls.  NEWDECL has been found to be
@@ -2048,6 +2093,7 @@ pushdecl (tree x)
                 just need to fall through to make the declaration in
                 this scope.  */
              nested = true;
+             x = visdecl;
            }
          else
            {
@@ -2057,30 +2103,6 @@ pushdecl (tree x)
            }
        }
     }
-  /* Similarly, a declaration of a function with static linkage at
-     block scope must be checked against any existing declaration
-     of that function at file scope.  */
-  else if (TREE_CODE (x) == FUNCTION_DECL && scope != file_scope
-          && !TREE_PUBLIC (x) && !DECL_INITIAL (x))
-    {
-      if (warn_nested_externs && !DECL_IN_SYSTEM_HEADER (x))
-       warning ("nested static declaration of %qD", x);
-
-      while (b && !B_IN_FILE_SCOPE (b))
-       b = b->shadowed;
-
-      if (b && same_translation_unit_p (x, b->decl)
-         && duplicate_decls (x, b->decl))
-       {
-         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
-         return b->decl;
-       }
-      else
-       {
-         bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false);
-         nested = true;
-       }
-    }
 
   warn_if_shadowing (x);
 
@@ -2129,12 +2151,11 @@ pushdecl_top_level (tree x)
 {
   tree name;
   bool nested = false;
-
-  gcc_assert (TREE_CODE (x) == VAR_DECL);
+  gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
 
   name = DECL_NAME (x);
 
 gcc_assert (!I_SYMBOL_BINDING (name));
gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
 
   if (TREE_PUBLIC (x))
     {
@@ -2697,8 +2718,6 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 {
   bool found_tag = false;
 
-  pending_invalid_xref = 0;
-
   if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
     {
       tree value = declspecs->type;
@@ -2722,8 +2741,29 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
                  warned = 1;
                }
            }
+         else if (!declspecs->tag_defined_p
+                  && declspecs->storage_class != csc_none)
+           {
+             if (warned != 1)
+               pedwarn ("empty declaration with storage class specifier "
+                        "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
+         else if (!declspecs->tag_defined_p
+                  && (declspecs->const_p
+                      || declspecs->volatile_p
+                      || declspecs->restrict_p))
+           {
+             if (warned != 1)
+               pedwarn ("empty declaration with type qualifier "
+                        "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
          else
            {
+             pending_invalid_xref = 0;
              t = lookup_tag (code, name, 1);
 
              if (t == 0)
@@ -2748,6 +2788,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
       warned = 1;
     }
 
+  pending_invalid_xref = 0;
+
   if (declspecs->inline_p)
     {
       error ("%<inline%> in empty declaration");
@@ -2932,6 +2974,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
 
   decl = grokdeclarator (declarator, declspecs,
                         NORMAL, initialized, NULL);
+  if (!decl)
+    return 0;
 
   deprecated_state = DEPRECATED_NORMAL;
 
@@ -3201,14 +3245,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
-       {
-         tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
-         set_user_assembler_name (builtin, asmspec);
-          if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
-            init_block_move_fn (asmspec);
-          else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
-            init_block_clear_fn (asmspec);
-        }
+       set_builtin_user_assembler_name (decl, asmspec);
       set_user_assembler_name (decl, asmspec);
     }
 
@@ -3476,6 +3513,7 @@ build_compound_literal (tree type, tree init)
       DECL_DEFER_OUTPUT (decl) = 1;
       DECL_COMDAT (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
       pushdecl (decl);
       rest_of_decl_compilation (decl, 1, 0);
     }
@@ -3789,10 +3827,6 @@ grokdeclarator (const struct c_declarator *declarator,
       && TREE_CODE (type) == INTEGER_TYPE)
     type = c_common_unsigned_type (type);
 
-  /* Check the type and width of a bit-field.  */
-  if (bitfield)
-    check_bitfield_type_and_width (&type, width, orig_name);
-
   /* Figure out the type qualifiers for the declaration.  There are
      two ways a declaration can become qualified.  One is something
      like `const int i' where the `const' is explicit.  Another is
@@ -4056,6 +4090,12 @@ grokdeclarator (const struct c_declarator *declarator,
                  }
                else
                  {
+                   /* Arrange for the SAVE_EXPR on the inside of the
+                      MINUS_EXPR, which allows the -1 to get folded
+                      with the +1 that happens when building TYPE_SIZE.  */
+                   if (size_varies)
+                     size = variable_size (size);
+
                    /* Compute the maximum valid index, that is, size
                       - 1.  Do the calculation in index_type, so that
                       if it is a variable the computations will be
@@ -4079,8 +4119,6 @@ grokdeclarator (const struct c_declarator *declarator,
                        continue;
                      }
                    
-                   if (size_varies)
-                     itype = variable_size (itype);
                    itype = build_index_type (itype);
                  }
              }
@@ -4114,14 +4152,9 @@ grokdeclarator (const struct c_declarator *declarator,
               zero.  */
            if (size && integer_zerop (size))
              {
-               layout_type (type);
                TYPE_SIZE (type) = bitsize_zero_node;
                TYPE_SIZE_UNIT (type) = size_zero_node;
              }
-           else if (declarator->kind == cdk_pointer)
-             /* We can never complete an array type which is the
-                target of a pointer, so go ahead and lay it out.  */
-             layout_type (type);
 
            if (decl_context != PARM
                && (array_ptr_quals != TYPE_UNQUALIFIED
@@ -4237,6 +4270,10 @@ grokdeclarator (const struct c_declarator *declarator,
 
   /* Now TYPE has the actual type.  */
 
+  /* Check the type and width of a bit-field.  */
+  if (bitfield)
+    check_bitfield_type_and_width (&type, width, orig_name);
+
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -4414,7 +4451,9 @@ grokdeclarator (const struct c_declarator *declarator,
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
        if (storage_class == csc_register || threadp)
-         error ("invalid storage class for function %qs", name);
+         {
+           error ("invalid storage class for function %qs", name);
+          }
        else if (current_scope != file_scope)
          {
            /* Function declaration not at file scope.  Storage
@@ -4427,8 +4466,14 @@ grokdeclarator (const struct c_declarator *declarator,
                if (pedantic)
                  pedwarn ("invalid storage class for function %qs", name);
              }
-           if (storage_class == csc_static)
-             error ("invalid storage class for function %qs", name);
+           else if (storage_class == csc_static)
+             {
+               error ("invalid storage class for function %qs", name);
+               if (funcdef_flag)
+                 storage_class = declspecs->storage_class = csc_none;
+               else
+                 return 0;
+             }
          }
 
        decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
@@ -4649,10 +4694,14 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
       tree parm, type, typelt;
       unsigned int parmno;
 
-      /* If the arg types are incomplete in a declaration, they must
-        include undefined tags.  These tags can never be defined in
-        the scope of the declaration, so the types can never be
-        completed, and no call can be compiled successfully.  */
+      /* If there is a parameter of incomplete type in a definition,
+        this is an error.  In a declaration this is valid, and a
+        struct or union type may be completed later, before any calls
+        or definition of the function.  In the case where the tag was
+        first declared within the parameter list, a warning has
+        already been given.  If a parameter has void type, then
+        however the function cannot be defined or called, so
+        warn.  */
 
       for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
           parm;
@@ -4676,13 +4725,13 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
                  TREE_VALUE (typelt) = error_mark_node;
                  TREE_TYPE (parm) = error_mark_node;
                }
-             else
+             else if (VOID_TYPE_P (type))
                {
                  if (DECL_NAME (parm))
-                   warning ("%Jparameter %u (%qD) has incomplete type",
+                   warning ("%Jparameter %u (%qD) has void type",
                             parm, parmno, parm);
                  else
-                   warning ("%Jparameter %u has incomplete type",
+                   warning ("%Jparameter %u has void type",
                             parm, parmno);
                }
            }
@@ -4837,10 +4886,13 @@ get_parm_info (bool ellipsis)
 
        case CONST_DECL:
        case TYPE_DECL:
+       case FUNCTION_DECL:
          /* CONST_DECLs appear here when we have an embedded enum,
             and TYPE_DECLs appear here when we have an embedded struct
             or union.  No warnings for this - we already warned about the
-            type itself.  */
+            type itself.  FUNCTION_DECLs appear when there is an implicit
+            function declaration in the parameter list.  */
+
          TREE_CHAIN (decl) = others;
          others = decl;
          /* fall through */
@@ -4857,7 +4909,6 @@ get_parm_info (bool ellipsis)
 
          /* Other things that might be encountered.  */
        case LABEL_DECL:
-       case FUNCTION_DECL:
        case VAR_DECL:
        default:
          gcc_unreachable ();
@@ -4874,11 +4925,13 @@ get_parm_info (bool ellipsis)
 }
 \f
 /* Get the struct, enum or union (CODE says which) with tag NAME.
-   Define the tag as a forward-reference if it is not defined.  */
+   Define the tag as a forward-reference if it is not defined.
+   Return a c_typespec structure for the type specifier.  */
 
-tree
-xref_tag (enum tree_code code, tree name)
+struct c_typespec
+parser_xref_tag (enum tree_code code, tree name)
 {
+  struct c_typespec ret;
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
@@ -4894,8 +4947,12 @@ xref_tag (enum tree_code code, tree name)
      this would not work properly if we return the reference found.
      (For example, with "struct foo" in an outer scope, "union foo;"
      must shadow that tag with a new one of union type.)  */
+  ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
   if (ref && TREE_CODE (ref) == code)
-    return ref;
+    {
+      ret.spec = ref;
+      return ret;
+    }
 
   /* If no such tag is yet defined, create a forward-reference node
      and record it as the "definition".
@@ -4918,7 +4975,18 @@ xref_tag (enum tree_code code, tree name)
 
   pushtag (name, ref);
 
-  return ref;
+  ret.spec = ref;
+  return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+   Define the tag as a forward-reference if it is not defined.
+   Return a tree for the type.  */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+  return parser_xref_tag (code, name).spec;
 }
 \f
 /* Make sure that the tag NAME is defined *in the current scope*
@@ -5004,27 +5072,29 @@ grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
         that took root before someone noticed the bug...  */
 
       tree type = declspecs->type;
+      bool type_ok = (TREE_CODE (type) == RECORD_TYPE
+                     || TREE_CODE (type) == UNION_TYPE);
+      bool ok = false;
 
-      if (type
-         && (TREE_CODE (type) == RECORD_TYPE
-             || TREE_CODE (type) == UNION_TYPE)
+      if (type_ok
          && (flag_ms_extensions || !declspecs->typedef_p))
        {
          if (flag_ms_extensions)
-           ; /* ok */
+           ok = true;
          else if (flag_iso)
-           goto warn_unnamed_field;
+           ok = false;
          else if (TYPE_NAME (type) == NULL)
-           ; /* ok */
+           ok = true;
          else
-           goto warn_unnamed_field;
+           ok = false;
        }
-      else
+      if (!ok)
        {
-       warn_unnamed_field:
-         warning ("declaration does not declare anything");
+         pedwarn ("declaration does not declare anything");
          return NULL_TREE;
        }
+      if (pedantic)
+       pedwarn ("ISO C doesn%'t support unnamed structs/unions");
     }
 
   value = grokdeclarator (declarator, declspecs, FIELD, false,
@@ -5118,9 +5188,22 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          break;
 
       if (x == 0)
-       pedwarn ("%s has no %s",
-                TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
-                fieldlist ? _("named members") : _("members"));
+       {
+         if (TREE_CODE (t) == UNION_TYPE)
+           {
+             if (fieldlist)
+               pedwarn ("union has no named members");
+             else
+               pedwarn ("union has no members");
+           }
+         else
+           {
+             if (fieldlist)
+               pedwarn ("struct has no named members");
+             else
+               pedwarn ("struct has no members");
+           }
+       }
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
@@ -5324,6 +5407,12 @@ finish_struct (tree t, tree fieldlist, tree attributes)
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
+  /* If we're inside a function proper, i.e. not file-scope and not still
+     parsing parameters, then arrange for the size of a variable sized type
+     to be bound now.  */
+  if (cur_stmt_list && variably_modified_type_p (t, NULL))
+    add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
+
   return t;
 }
 
@@ -5661,11 +5750,9 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
   DECL_INITIAL (decl1) = error_mark_node;
 
   /* If this definition isn't a prototype and we had a prototype declaration
-     before, copy the arg type info from that prototype.
-     But not if what we had before was a builtin function.  */
+     before, copy the arg type info from that prototype.  */
   old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
   if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
-      && !DECL_BUILT_IN (old_decl)
       && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
                    TREE_TYPE (TREE_TYPE (old_decl)))
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
@@ -5959,7 +6046,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
       if (TREE_CODE (parm) != PARM_DECL)
        continue;
 
-      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+      if (TREE_TYPE (parm) != error_mark_node
+         && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
          error ("%Jparameter %qD has incomplete type", parm, parm);
          TREE_TYPE (parm) = error_mark_node;
@@ -6153,8 +6241,11 @@ store_parm_decls (void)
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
   /* ??? Insert the contents of the pending sizes list into the function
-     to be evaluated.  This just changes mis-behavior until assign_parms
-     phase ordering problems are resolved.  */
+     to be evaluated.  The only reason left to have this is
+       void foo(int n, int array[n++])
+     because we throw away the array type in favor of a pointer type, and
+     thus won't naturally see the SAVE_EXPR containing the increment.  All
+     other pending sizes would be handled by gimplify_parameters.  */
   {
     tree t;
     for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
@@ -6230,7 +6321,13 @@ finish_function (void)
       else
        {
          if (flag_isoc99)
-           c_finish_return (integer_zero_node);
+           {
+             tree stmt = c_finish_return (integer_zero_node);
+             /* Hack.  We don't want the middle-end to warn that this
+                return is unreachable, so put the statement on the
+                special line 0.  */
+             annotate_with_file_line (stmt, input_filename, 0);
+           }
        }
     }
 
@@ -6638,6 +6735,7 @@ build_null_declspecs (void)
   ret->storage_class = csc_none;
   ret->non_sc_seen_p = false;
   ret->typedef_p = false;
+  ret->tag_defined_p = false;
   ret->explicit_signed_p = false;
   ret->deprecated_p = false;
   ret->default_int_p = false;
@@ -6693,8 +6791,9 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, tree type)
+declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
 {
+  tree type = spec.spec;
   specs->non_sc_seen_p = true;
   if (TREE_DEPRECATED (type))
     specs->deprecated_p = true;
@@ -6817,7 +6916,7 @@ declspecs_add_type (struct c_declspecs *specs, tree type)
              break;
            case RID_COMPLEX:
              dupe = specs->complex_p;
-             if (pedantic && !flag_isoc99)
+             if (pedantic && !flag_isoc99 && !in_system_header)
                pedwarn ("ISO C90 does not support complex types");
              if (specs->typespec_word == cts_void)
                error ("both %<complex%> and %<void%> in "
@@ -6970,7 +7069,13 @@ declspecs_add_type (struct c_declspecs *specs, tree type)
        specs->type = TREE_TYPE (t);
     }
   else if (TREE_CODE (type) != ERROR_MARK)
-    specs->type = type;
+    {
+      if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
+       specs->tag_defined_p = true;
+      if (spec.kind == ctsk_typeof)
+       specs->typedef_p = true;
+      specs->type = type;
+    }
 
   return specs;
 }
@@ -7295,11 +7400,6 @@ c_write_global_declarations (void)
   /* We're done parsing; proceed to optimize and emit assembly.
      FIXME: shouldn't be the front end's responsibility to call this.  */
   cgraph_optimize ();
-
-  /* Presently this has to happen after cgraph_optimize.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  if (flag_mudflap)
-    mudflap_finish_file ();
 }
 
 #include "gt-c-decl.h"