re PR c/14516 (-fleading-underscore does not work correctly for file static variables)
[gcc.git] / gcc / c-decl.c
index 56351512ff48cea6abad991388694247706ba86d..ff535524c4e4f6a1c1e6990f1b2298f76dd491c9 100644 (file)
@@ -377,7 +377,8 @@ static bool next_is_function_body;
 
 /* Functions called automatically at the beginning and end of execution.  */
 
-tree static_ctors, static_dtors;
+static GTY(()) tree static_ctors;
+static GTY(()) tree static_dtors;
 
 /* Forward declarations.  */
 static tree lookup_name_in_scope (tree, struct c_scope *);
@@ -427,7 +428,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
       binding_freelist = b->prev;
     }
   else
-    b = ggc_alloc (sizeof (struct c_binding));
+    b = GGC_NEW (struct c_binding);
 
   b->shadowed = 0;
   b->decl = decl;
@@ -602,7 +603,7 @@ push_scope (void)
          scope_freelist = scope->outer;
        }
       else
-       scope = ggc_alloc_cleared (sizeof (struct c_scope));
+       scope = GGC_CNEW (struct c_scope);
 
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
@@ -621,6 +622,16 @@ push_scope (void)
     }
 }
 
+/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT.  */
+
+static void
+set_type_context (tree type, tree context)
+{
+  for (type = TYPE_MAIN_VARIANT (type); type;
+       type = TYPE_NEXT_VARIANT (type))
+    TYPE_CONTEXT (type) = context;
+}
+
 /* Exit a scope.  Restore the state of the identifier-decl mappings
    that were in effect when this scope was entered.  Return a BLOCK
    node containing all the DECLs in this scope that are of interest
@@ -710,7 +721,7 @@ pop_scope (void)
        case ENUMERAL_TYPE:
        case UNION_TYPE:
        case RECORD_TYPE:
-         TYPE_CONTEXT (p) = context;
+         set_type_context (p, context);
 
          /* Types may not have tag-names, in which case the type
             appears in the bindings list with b->id NULL.  */
@@ -735,9 +746,7 @@ pop_scope (void)
          goto common_symbol;
 
        case VAR_DECL:
-         /* Warnings for unused variables.  Keep this in sync with
-            stmt.c:warn_about_unused_variables, which we cannot use
-            since it expects a different data structure.  */
+         /* Warnings for unused variables.  */
          if (warn_unused_variable
              && !TREE_USED (p)
              && !DECL_IN_SYSTEM_HEADER (p)
@@ -760,11 +769,17 @@ pop_scope (void)
              TREE_CHAIN (p) = BLOCK_VARS (block);
              BLOCK_VARS (block) = p;
            }
-         /* If this is the file scope, must set DECL_CONTEXT on
-            these.  Do so even for externals, so that
-            same_translation_unit_p works.  */
-         if (scope == file_scope)
-           DECL_CONTEXT (p) = context;
+         /* If this is the file scope, and we are processing more
+            than one translation unit in this compilation, set
+            DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
+            This makes same_translation_unit_p work, and causes
+            static declarations to be given disambiguating suffixes.  */
+         if (scope == file_scope && num_in_fnames > 1)
+           {
+             DECL_CONTEXT (p) = context;
+             if (TREE_CODE (p) == TYPE_DECL)
+               set_type_context (TREE_TYPE (p), context);
+           }
 
          /* Fall through.  */
          /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
@@ -851,17 +866,18 @@ pop_file_scope (void)
      still works without it.  */
   finish_fname_decls ();
 
-  /* Kludge: don't actually pop the file scope if generating a
-     precompiled header, so that macros and local symbols are still
-     visible to the PCH generator.  */
+  /* This is the point to write out a PCH if we're doing that.
+     In that case we do not want to do anything else.  */
   if (pch_file)
-    return;
+    {
+      c_common_write_pch ();
+      return;
+    }
 
-  /* And pop off the file scope.  */
+  /* Pop off the file scope and close this translation unit.  */
   pop_scope ();
   file_scope = 0;
-
-  cpp_undef_all (parse_in);
+  cgraph_finalize_compilation_unit ();
 }
 
 /* Insert BLOCK at the end of the list of subblocks of the current
@@ -1210,7 +1226,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
              && !(DECL_DECLARED_INLINE_P (olddecl)
                   && DECL_EXTERNAL (olddecl)
                   && !(DECL_DECLARED_INLINE_P (newdecl)
-                       && DECL_EXTERNAL (newdecl))))
+                       && DECL_EXTERNAL (newdecl)
+                       && same_translation_unit_p (olddecl, newdecl))))
            {
              error ("%Jredefinition of '%D'", newdecl, newdecl);
              locate_old_decl (olddecl, error);
@@ -1308,7 +1325,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        {
          if (DECL_EXTERNAL (newdecl))
            {
-             if (warn_traditional)
+             if (!DECL_FILE_SCOPE_P (olddecl))
+               {
+                 error ("%Jextern declaration of %qD follows "
+                        "declaration with no linkage", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             else if (warn_traditional)
                {
                  warning ("%Jnon-static declaration of '%D' follows "
                           "static declaration", newdecl, newdecl);
@@ -1330,13 +1354,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        }
       /* Two objects with the same name declared at the same block
         scope must both be external references (6.7p3).  */
-      else if (!DECL_FILE_SCOPE_P (newdecl)
-              && DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
-              && (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
+      else if (!DECL_FILE_SCOPE_P (newdecl))
        {
          if (DECL_EXTERNAL (newdecl))
-           error ("%Jextern declaration of '%D' follows "
-                  "declaration with no linkage", newdecl, newdecl);
+           abort ();
          else if (DECL_EXTERNAL (olddecl))
            error ("%Jdeclaration of '%D' with no linkage follows "
                   "extern declaration", newdecl, newdecl);
@@ -1350,9 +1371,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
     }
 
   /* warnings */
-  /* All decls must agree on a non-default visibility.  */
-  if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
-      && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
+  /* All decls must agree on a visibility.  */
+  if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
       warning ("%Jredeclaration of '%D' with different visibility "
@@ -1380,8 +1400,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       /* Inline declaration after use or definition.
         ??? Should we still warn about this now we have unit-at-a-time
-        mode and can get it right?  */
-      if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
+        mode and can get it right?
+        Definitely don't complain if the decls are in different translation
+        units.  */
+      if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
+         && same_translation_unit_p (olddecl, newdecl))
        {
          if (TREE_USED (olddecl))
            {
@@ -1424,6 +1447,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
         definition.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL
           && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
+      /* Don't warn about redundant redeclarations of builtins. */
+      && !(TREE_CODE (newdecl) == FUNCTION_DECL
+          && !DECL_BUILT_IN (newdecl)
+          && DECL_BUILT_IN (olddecl)
+          && !C_DECL_DECLARED_BUILTIN (olddecl))
       /* Don't warn about an extern followed by a definition.  */
       && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
       /* Don't warn about forward parameter decls.  */
@@ -1545,9 +1573,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
      Currently, it can only be defined in the prototype.  */
   COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
-  /* If either declaration has a nondefault visibility, use it.  */
-  if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
-    DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+  /* 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)
     {
@@ -1664,14 +1695,16 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
     }
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDDECL's DECL_UID.  */
+     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));
     DECL_UID (olddecl) = olddecl_uid;
+    DECL_CONTEXT (olddecl) = olddecl_context;
   }
 
   /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
@@ -1681,7 +1714,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       && (TREE_CODE (olddecl) == FUNCTION_DECL
          || (TREE_CODE (olddecl) == VAR_DECL
              && TREE_STATIC (olddecl))))
-    make_decl_rtl (olddecl, NULL);
+    make_decl_rtl (olddecl);
 }
 
 /* Handle when a new declaration NEWDECL has the same name as an old
@@ -1704,45 +1737,49 @@ duplicate_decls (tree newdecl, tree olddecl)
 }
 
 \f
-/* Check whether decl-node NEW shadows an existing declaration.  */
+/* Check whether decl-node NEW_DECL shadows an existing declaration.  */
 static void
-warn_if_shadowing (tree new)
+warn_if_shadowing (tree new_decl)
 {
   struct c_binding *b;
 
   /* Shadow warnings wanted?  */
   if (!warn_shadow
       /* No shadow warnings for internally generated vars.  */
-      || DECL_IS_BUILTIN (new)
+      || DECL_IS_BUILTIN (new_decl)
       /* No shadow warnings for vars made for inlining.  */
-      || DECL_FROM_INLINE (new)
+      || 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) == PARM_DECL && current_scope->outer->parm_flag))
+      || (TREE_CODE (new_decl) == PARM_DECL && current_scope->outer->parm_flag))
     return;
 
   /* Is anything being shadowed?  Invisible decls do not count.  */
-  for (b = I_SYMBOL_BINDING (DECL_NAME (new)); b; b = b->shadowed)
-    if (b->decl && b->decl != new && !b->invisible)
+  for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
+    if (b->decl && b->decl != new_decl && !b->invisible)
       {
-       tree old = b->decl;
+       tree old_decl = b->decl;
 
-       if (TREE_CODE (old) == PARM_DECL)
-         warning ("%Jdeclaration of '%D' shadows a parameter", new, new);
-       else if (DECL_FILE_SCOPE_P (old))
+       if (TREE_CODE (old_decl) == PARM_DECL)
+         warning ("%Jdeclaration of '%D' shadows a parameter",
+                  new_decl, new_decl);
+       else if (DECL_FILE_SCOPE_P (old_decl))
          warning ("%Jdeclaration of '%D' shadows a global declaration",
-                  new, new);
-       else if (TREE_CODE (old) == FUNCTION_DECL && DECL_BUILT_IN (old))
+                  new_decl, new_decl);
+       else if (TREE_CODE (old_decl) == FUNCTION_DECL
+                && DECL_BUILT_IN (old_decl))
          warning ("%Jdeclaration of '%D' shadows a built-in function",
-                  new, new);
+                  new_decl, new_decl);
        else
-         warning ("%Jdeclaration of '%D' shadows a previous local", new, new);
+         warning ("%Jdeclaration of '%D' shadows a previous local",
+                  new_decl, new_decl);
 
-       if (TREE_CODE (old) != FUNCTION_DECL || !DECL_BUILT_IN (old))
-         warning ("%Jshadowed declaration is here", old);
+       if (TREE_CODE (old_decl) != FUNCTION_DECL
+           || ! DECL_BUILT_IN (old_decl))
+         warning ("%Jshadowed declaration is here", old_decl);
 
        break;
       }
@@ -1831,7 +1868,7 @@ pushdecl (tree x)
 
   /* Functions need the lang_decl data.  */
   if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
-    DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_decl));
+    DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
 
   /* Must set DECL_CONTEXT for everything not at file scope or
      DECL_FILE_SCOPE_P won't work.  Local externs don't count
@@ -1892,14 +1929,13 @@ pushdecl (tree x)
         they are in different translation units.  In any case,
         the static does not go in the externals scope.  */
       if (b
-         && (DECL_EXTERNAL (x) || TREE_PUBLIC (x)
-             || same_translation_unit_p (x, b->decl))
+         && (TREE_PUBLIC (x) || 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 if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+      else if (TREE_PUBLIC (x))
        {
          bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
          nested = true;
@@ -1928,7 +1964,7 @@ pushdecl (tree x)
          bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false);
          nested = true;
        }
-    }      
+    }
 
   warn_if_shadowing (x);
 
@@ -1986,7 +2022,7 @@ pushdecl_top_level (tree x)
   if (I_SYMBOL_BINDING (name))
     abort ();
 
-  if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+  if (TREE_PUBLIC (x))
     {
       bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
       nested = true;
@@ -2046,6 +2082,23 @@ implicitly_declare (tree functionid)
              implicit_decl_warning (functionid, decl);
              C_DECL_IMPLICIT (decl) = 1;
            }
+         if (DECL_BUILT_IN (decl))
+           {
+             if (!comptypes (default_function_type, TREE_TYPE (decl)))
+               {
+                 warning ("incompatible implicit declaration of built-in"
+                          " function %qD", decl);
+               }
+           }
+         else
+           {
+             if (!comptypes (default_function_type, TREE_TYPE (decl)))
+               {
+                 error ("incompatible implicit declaration of function %qD",
+                        decl);
+                 locate_old_decl (decl, error);
+               }
+           }
          bind (functionid, decl, current_scope,
                /*invisible=*/false, /*nested=*/true);
          return decl;
@@ -2064,7 +2117,7 @@ implicitly_declare (tree functionid)
   decl = pushdecl (decl);
 
   /* No need to call objc_check_decl here - it's a function type.  */
-  rest_of_decl_compilation (decl, NULL, 0, 0);
+  rest_of_decl_compilation (decl, 0, 0);
 
   /* Write a record describing this implicit function declaration
      to the prototypes file (if requested).  */
@@ -2449,15 +2502,15 @@ c_make_fname_decl (tree id, int type_dep)
 
 tree
 builtin_function (const char *name, tree type, int function_code,
-                 enum built_in_class class, const char *library_name,
+                 enum built_in_class cl, const char *library_name,
                  tree attrs)
 {
   tree id = get_identifier (name);
   tree decl = build_decl (FUNCTION_DECL, id, type);
   TREE_PUBLIC (decl) = 1;
   DECL_EXTERNAL (decl) = 1;
-  DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared (sizeof (struct lang_decl));
-  DECL_BUILT_IN_CLASS (decl) = class;
+  DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
+  DECL_BUILT_IN_CLASS (decl) = cl;
   DECL_FUNCTION_CODE (decl) = function_code;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
@@ -2499,12 +2552,10 @@ shadow_tag (tree declspecs)
   shadow_tag_warned (declspecs, 0);
 }
 
+/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
+   but no pedwarn.  */
 void
 shadow_tag_warned (tree declspecs, int warned)
-
-
-     /* 1 => we have done a pedwarn.  2 => we have done a warning, but
-       no pedwarn.  */
 {
   int found_tag = 0;
   tree link;
@@ -2620,33 +2671,33 @@ set_array_declarator_type (tree decl, tree type, int abstract_p)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (tree typename)
+groktypename (tree type_name)
 {
   tree specs, attrs;
 
-  if (TREE_CODE (typename) != TREE_LIST)
-    return typename;
+  if (TREE_CODE (type_name) != TREE_LIST)
+    return type_name;
 
-  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+  split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
 
-  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
+  type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, 0,
                             NULL);
 
   /* Apply attributes.  */
-  decl_attributes (&typename, attrs, 0);
+  decl_attributes (&type_name, attrs, 0);
 
-  return typename;
+  return type_name;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
 
 tree
-groktypename_in_parm_context (tree typename)
+groktypename_in_parm_context (tree type_name)
 {
-  if (TREE_CODE (typename) != TREE_LIST)
-    return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
+  if (TREE_CODE (type_name) != TREE_LIST)
+    return type_name;
+  return grokdeclarator (TREE_VALUE (type_name),
+                        TREE_PURPOSE (type_name),
                         PARM, 0, NULL);
 }
 
@@ -2740,7 +2791,6 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
 
   if (initialized)
     {
-      DECL_EXTERNAL (decl) = 0;
       if (current_scope == file_scope)
        TREE_STATIC (decl) = 1;
 
@@ -2807,6 +2857,9 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
 
+  if (initialized)
+    DECL_EXTERNAL (tem) = 0;
+
   return tem;
 }
 
@@ -2840,8 +2893,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
     store_init_value (decl, init);
 
   if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
-                   || TREE_CODE (decl) == FUNCTION_DECL
-                   || TREE_CODE (decl) == FIELD_DECL))
+                           || TREE_CODE (decl) == FUNCTION_DECL
+                           || TREE_CODE (decl) == FIELD_DECL))
     objc_check_decl (decl);
 
   /* Deduce size of array from initialization, if not already known.  */
@@ -2882,7 +2935,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
         in the array, because we start counting at zero.  Therefore,
         warn only if the value is less than zero.  */
       else if (pedantic && TYPE_DOMAIN (type) != 0
-             && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+              && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
        error ("%Jzero or negative size array '%D'", decl, decl);
 
       layout_decl (decl, 0);
@@ -2898,22 +2951,20 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          /* Don't give an error if we already gave one earlier.  */
          && TREE_TYPE (decl) != error_mark_node
          && (TREE_STATIC (decl)
-             ?
-               /* A static variable with an incomplete type
-                  is an error if it is initialized.
-                  Also if it is not file scope.
-                  Otherwise, let it through, but if it is not `extern'
-                  then it may cause an error message later.  */
-               (DECL_INITIAL (decl) != 0
+             /* A static variable with an incomplete type
+                is an error if it is initialized.
+                Also if it is not file scope.
+                Otherwise, let it through, but if it is not `extern'
+                then it may cause an error message later.  */
+             ? (DECL_INITIAL (decl) != 0
                 || !DECL_FILE_SCOPE_P (decl))
-             :
-               /* An automatic variable with an incomplete type
-                  is an error.  */
-               !DECL_EXTERNAL (decl)))
-       {
-         error ("%Jstorage size of '%D' isn't known", decl, decl);
-         TREE_TYPE (decl) = error_mark_node;
-       }
+             /* An automatic variable with an incomplete type
+                is an error.  */
+             : !DECL_EXTERNAL (decl)))
+        {
+          error ("%Jstorage size of '%D' isn't known", decl, decl);
+          TREE_TYPE (decl) = error_mark_node;
+        }
 
       if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
          && DECL_SIZE (decl) != 0)
@@ -2933,31 +2984,16 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
      was a normal built-in.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
-      /* ASMSPEC is given, and not the name of a register.  Mark the
-      name with a star so assemble_name won't munge it.  */
-      char *starred = alloca (strlen (asmspec) + 2);
-      starred[0] = '*';
-      strcpy (starred + 1, asmspec);
-
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
        {
          tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
-         SET_DECL_RTL (builtin, NULL_RTX);
-         change_decl_assembler_name (builtin, get_identifier (starred));
-#ifdef TARGET_MEM_FUNCTIONS
-         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
-           init_block_move_fn (starred);
-         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
-           init_block_clear_fn (starred);
-#else
-         if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
-           init_block_move_fn (starred);
-         else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
-           init_block_clear_fn (starred);
-#endif
-       }
-      SET_DECL_RTL (decl, NULL_RTX);
-      change_decl_assembler_name (decl, get_identifier (starred));
+         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_user_assembler_name (decl, asmspec);
     }
 
   /* If #pragma weak was used, mark the decl weak now.  */
@@ -2974,6 +3010,25 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
       if (c_dialect_objc ())
        objc_check_decl (decl);
 
+      if (asmspec) 
+       {
+         /* If this is not a static variable, issue a warning.
+            It doesn't make any sense to give an ASMSPEC for an
+            ordinary, non-register local variable.  Historically,
+            GCC has accepted -- but ignored -- the ASMSPEC in
+            this case.  */
+         if (! DECL_FILE_SCOPE_P (decl)
+             && TREE_CODE (decl) == VAR_DECL
+             && !C_DECL_REGISTER (decl)
+             && !TREE_STATIC (decl))
+           warning ("%Jignoring asm-specifier for non-static local "
+                    "variable '%D'", decl, decl);
+         else if (C_DECL_REGISTER (decl))
+           change_decl_assembler_name (decl, get_identifier (asmspec));
+         else
+           set_user_assembler_name (decl, asmspec);
+       }
+      
       if (DECL_FILE_SCOPE_P (decl))
        {
          if (DECL_INITIAL (decl) == NULL_TREE
@@ -2982,44 +3037,27 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
               when a tentative file-scope definition is seen.
               But at end of compilation, do output code for them.  */
            DECL_DEFER_OUTPUT (decl) = 1;
-         rest_of_decl_compilation (decl, asmspec, true, 0);
+         rest_of_decl_compilation (decl, true, 0);
        }
       else
        {
-         /* This is a local variable.  If there is an ASMSPEC, the
-            user has requested that we handle it specially.  */
-         if (asmspec)
+         /* In conjunction with an ASMSPEC, the `register'
+            keyword indicates that we should place the variable
+            in a particular register.  */
+         if (asmspec && C_DECL_REGISTER (decl))
            {
-             /* In conjunction with an ASMSPEC, the `register'
-                keyword indicates that we should place the variable
-                in a particular register.  */
-             if (C_DECL_REGISTER (decl))
-               {
-                 DECL_HARD_REGISTER (decl) = 1;
-                 /* This cannot be done for a structure with volatile
-                    fields, on which DECL_REGISTER will have been
-                    reset.  */
-                 if (!DECL_REGISTER (decl))
-                   error ("cannot put object with volatile field into register");
-               }
-
-             /* If this is not a static variable, issue a warning.
-                It doesn't make any sense to give an ASMSPEC for an
-                ordinary, non-register local variable.  Historically,
-                GCC has accepted -- but ignored -- the ASMSPEC in
-                this case.  */
-             if (TREE_CODE (decl) == VAR_DECL
-                 && !C_DECL_REGISTER (decl)
-                 && !TREE_STATIC (decl))
-               warning ("%Jignoring asm-specifier for non-static local "
-                         "variable '%D'", decl, decl);
-             else
-               change_decl_assembler_name (decl, get_identifier (asmspec));
+             DECL_HARD_REGISTER (decl) = 1;
+             /* This cannot be done for a structure with volatile
+                fields, on which DECL_REGISTER will have been
+                reset.  */
+             if (!DECL_REGISTER (decl))
+               error ("cannot put object with volatile field into register");
            }
 
          if (TREE_CODE (decl) != FUNCTION_DECL)
            add_stmt (build_stmt (DECL_EXPR, decl));
        }
+  
 
       if (!DECL_FILE_SCOPE_P (decl))
        {
@@ -3044,10 +3082,10 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
   if (TREE_CODE (decl) == TYPE_DECL)
     {
       if (!DECL_FILE_SCOPE_P (decl)
-         && variably_modified_type_p (TREE_TYPE (decl)))
+         && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
        add_stmt (build_stmt (DECL_EXPR, decl));
 
-      rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+      rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
     }
 
   /* At the end of a declaration, throw away any variable type sizes
@@ -3184,7 +3222,7 @@ build_compound_literal (tree type, tree init)
       DECL_COMDAT (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
       pushdecl (decl);
-      rest_of_decl_compilation (decl, NULL, 1, 0);
+      rest_of_decl_compilation (decl, 1, 0);
     }
 
   return complit;
@@ -3223,7 +3261,6 @@ complete_array_type (tree type, tree initial_value, int do_default)
                maxindex = fold (build (PLUS_EXPR, integer_type_node,
                                        maxindex, integer_one_node));
            }
-         maxindex = copy_node (maxindex);
        }
       else
        {
@@ -3247,7 +3284,7 @@ complete_array_type (tree type, tree initial_value, int do_default)
     {
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
-       TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+       abort ();
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -4151,21 +4188,15 @@ grokdeclarator (tree declarator, tree declspecs,
             qualify the return type, not the function type.  */
          if (type_quals)
            {
-             /* Type qualifiers on a function return type are normally
-                permitted by the standard but have no effect, so give a
-                warning at -Wextra.  Qualifiers on a void return type have
-                meaning as a GNU extension, and are banned on function
-                definitions in ISO C.  FIXME: strictly we shouldn't
-                pedwarn for qualified void return types except on function
-                definitions, but not doing so could lead to the undesirable
-                state of a "volatile void" function return type not being
-                warned about, and a use of the function being compiled
-                with GNU semantics, with no diagnostics under -pedantic.  */
-             if (VOID_TYPE_P (type) && pedantic && !in_system_header)
-               pedwarn ("ISO C forbids qualified void function return type");
-             else if (extra_warnings
-                      && !(VOID_TYPE_P (type)
-                           && type_quals == TYPE_QUAL_VOLATILE))
+             /* Type qualifiers on a function return type are
+                normally permitted by the standard but have no
+                effect, so give a warning at -Wreturn-type.
+                Qualifiers on a void return type are banned on
+                function definitions in ISO C; GCC used to used them
+                for noreturn functions.  */
+             if (VOID_TYPE_P (type) && really_funcdef)
+               pedwarn ("function definition has qualified void return type");
+             else if (warn_return_type)
                warning ("type qualifiers ignored on function return type");
 
              type = c_build_qualified_type (type, type_quals);
@@ -4461,14 +4492,6 @@ grokdeclarator (tree declarator, tree declspecs,
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
-       /* Every function declaration is "external"
-          except for those which are inside a function body
-          in which `auto' is used.
-          That is a case not specified by ANSI C,
-          and we use it for forward declarations for nested functions.  */
-       int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
-                         || current_scope == file_scope);
-
        if (specbits & (1 << (int) RID_AUTO)
            && (pedantic || current_scope == file_scope))
          pedwarn ("invalid storage class for function `%s'", name);
@@ -4488,19 +4511,27 @@ grokdeclarator (tree declarator, tree declspecs,
        decl = build_decl_attribute_variant (decl, decl_attr);
 
        DECL_LANG_SPECIFIC (decl)
-         = ggc_alloc_cleared (sizeof (struct lang_decl));
+         = GGC_CNEW (struct lang_decl);
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
 
-       /* GNU C interprets a `volatile void' return type to indicate
+       /* GNU C interprets a volatile-qualified function type to indicate
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
            && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          warning ("`noreturn' function returns non-void value");
 
-       if (extern_ref)
+       /* Every function declaration is an external reference
+          (DECL_EXTERNAL) except for those which are not at file
+          scope and are explicitly declared "auto".  This is
+          forbidden by standard C (C99 6.7.1p5) and is interpreted by
+          GCC to signify a forward declaration of a nested function.  */
+       if ((specbits & (1 << RID_AUTO)) && current_scope != file_scope)
+         DECL_EXTERNAL (decl) = 0;
+       else
          DECL_EXTERNAL (decl) = 1;
+
        /* Record absence of global scope for `static' or `auto'.  */
        TREE_PUBLIC (decl)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
@@ -4586,7 +4617,10 @@ grokdeclarator (tree declarator, tree declspecs,
        if (inlinep)
          pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
 
-       DECL_EXTERNAL (decl) = extern_ref;
+       /* At file scope, an initialized extern declaration may follow
+          a static declaration.  In that case, DECL_EXTERNAL will be
+          reset later in start_decl.  */
+       DECL_EXTERNAL (decl) = !!(specbits & (1 << (int) RID_EXTERN));
 
        /* At file scope, the presence of a `static' or `register' storage
           class specifier, or the absence of all storage class specifiers
@@ -5169,9 +5203,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes,m which is found in the DECL_INITIAL.
-     Store 0 there, except for ": 0" fields (so we can find them
-     and delete them, below).  */
+     Also process specified field sizes, found in the DECL_INITIAL,
+     storing 0 there after the type has been changed to precision equal
+     to its width, rather than the precision of the specified standard
+     type.  (Correct layout requires the original type to have been preserved
+     until now.)  */
 
   saw_named_field = 0;
   for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5215,8 +5251,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          SET_DECL_C_BIT_FIELD (x);
        }
 
-      DECL_INITIAL (x) = 0;
-
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -5257,12 +5291,21 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
   layout_type (t);
 
-  /* Delete all zero-width bit-fields from the fieldlist.  */
+  /* Give bit-fields their proper types.  */
   {
     tree *fieldlistp = &fieldlist;
     while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
-       *fieldlistp = TREE_CHAIN (*fieldlistp);
+      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+         && TREE_TYPE (*fieldlistp) != error_mark_node)
+       {
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+         tree type = TREE_TYPE (*fieldlistp);
+         if (width != TYPE_PRECISION (type))
+           TREE_TYPE (*fieldlistp)
+             = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+         DECL_INITIAL (*fieldlistp) = 0;
+       }
       else
        fieldlistp = &TREE_CHAIN (*fieldlistp);
   }
@@ -5297,8 +5340,9 @@ finish_struct (tree t, tree fieldlist, tree attributes)
           ensure that this lives as long as the rest of the struct decl.
           All decls in an inline function need to be saved.  */
 
-        space = ggc_alloc_cleared (sizeof (struct lang_type));
-        space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+        space = GGC_CNEW (struct lang_type);
+        space2 = GGC_NEWVAR (struct sorted_fields_type,
+                            sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
         len = 0;
        space->s = space2;
@@ -5354,7 +5398,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          layout_decl (decl, 0);
          if (c_dialect_objc ())
            objc_check_decl (decl);
-         rest_of_decl_compilation (decl, NULL, toplevel, 0);
+         rest_of_decl_compilation (decl, toplevel, 0);
          if (! toplevel)
            expand_decl (decl);
        }
@@ -5521,7 +5565,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
   /* Record the min/max values so that we can warn about bit-field
      enumerations that are too small for the values.  */
-  lt = ggc_alloc_cleared (sizeof (struct lang_type));
+  lt = GGC_CNEW (struct lang_type);
   lt->enum_min = minnode;
   lt->enum_max = maxnode;
   TYPE_LANG_SPECIFIC (enumtype) = lt;
@@ -5639,7 +5683,7 @@ int
 start_function (tree declspecs, tree declarator, tree attributes)
 {
   tree decl1, old_decl;
-  tree restype;
+  tree restype, resdecl;
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
@@ -5691,11 +5735,12 @@ start_function (tree declspecs, tree declarator, tree attributes)
   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)
-      && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
-         == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
+      && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                   TREE_TYPE (TREE_TYPE (old_decl)))
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
     {
-      TREE_TYPE (decl1) = TREE_TYPE (old_decl);
+      TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+                                         TREE_TYPE (decl1));
       current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
     }
 
@@ -5834,8 +5879,11 @@ start_function (tree declspecs, tree declarator, tree attributes)
       else
        restype = integer_type_node;
     }
-  DECL_RESULT (current_function_decl)
-    = build_decl (RESULT_DECL, NULL_TREE, restype);
+
+  resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+  DECL_ARTIFICIAL (resdecl) = 1;
+  DECL_IGNORED_P (resdecl) = 1;
+  DECL_RESULT (current_function_decl) = resdecl;
 
   start_fname_decls ();
 
@@ -6420,7 +6468,7 @@ void
 c_push_function_context (struct function *f)
 {
   struct language_function *p;
-  p = ggc_alloc (sizeof (struct language_function));
+  p = GGC_NEW (struct language_function);
   f->language = p;
 
   p->base.x_stmt_tree = c_stmt_tree;
@@ -6474,7 +6522,7 @@ c_dup_lang_specific_decl (tree decl)
   if (!DECL_LANG_SPECIFIC (decl))
     return;
 
-  ld = ggc_alloc (sizeof (struct lang_decl));
+  ld = GGC_NEW (struct lang_decl);
   memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
   DECL_LANG_SPECIFIC (decl) = ld;
 }
@@ -6508,7 +6556,7 @@ current_stmt_tree (void)
    C.  */
 
 int
-anon_aggr_type_p (tree node ATTRIBUTE_UNUSED)
+anon_aggr_type_p (tree ARG_UNUSED (node))
 {
   return 0;
 }
@@ -6540,12 +6588,15 @@ identifier_global_value (tree t)
 void
 record_builtin_type (enum rid rid_index, const char *name, tree type)
 {
-  tree id;
+  tree id, decl;
   if (name == 0)
     id = ridpointers[(int) rid_index];
   else
     id = get_identifier (name);
-  pushdecl (build_decl (TYPE_DECL, id, type));
+  decl = build_decl (TYPE_DECL, id, type);
+  pushdecl (decl);
+  if (debug_hooks->type_decl)
+    debug_hooks->type_decl (decl, false);
 }
 
 /* Build the void_list_node (void_type_node having been created).  */
@@ -6576,12 +6627,31 @@ make_pointer_declarator (tree type_quals_attrs, tree target)
   return build1 (INDIRECT_REF, quals, itarget);
 }
 
-/* Perform final processing on file-scope data.  */
+/* Synthesize a function which calls all the global ctors or global
+   dtors in this file.  This is only used for targets which do not
+   support .ctors/.dtors sections.  FIXME: Migrate into cgraph.  */
+static void
+build_cdtor (int method_type, tree cdtors)
+{
+  tree body = 0;
+
+  if (!cdtors)
+    return;
+
+  for (; cdtors; cdtors = TREE_CHAIN (cdtors))
+    append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
+                             &body);
+
+  cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
+}
+
+/* Perform final processing on one file scope's declarations (or the
+   external scope's declarations), GLOBALS.  */
 static void
 c_write_global_declarations_1 (tree globals)
 {
   size_t len = list_length (globals);
-  tree *vec = xmalloc (sizeof (tree) * len);
+  tree *vec = XNEWVEC (tree, len);
   size_t i;
   tree decl;
 
@@ -6598,20 +6668,43 @@ c_write_global_declarations_1 (tree globals)
 void
 c_write_global_declarations (void)
 {
-  tree t;
+  tree ext_block, t;
 
   /* We don't want to do this if generating a PCH.  */
   if (pch_file)
     return;
 
-  /* Process all file scopes in this compilation.  */
+  /* Don't waste time on further processing if -fsyntax-only or we've
+     encountered errors.  */
+  if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+    return;
+
+  /* Close the external scope.  */
+  ext_block = pop_scope ();
+  external_scope = 0;
+  if (current_scope)
+    abort ();
+
+  /* Process all file scopes in this compilation, and the external_scope,
+     through wrapup_global_declarations and check_global_declarations.  */
   for (t = all_translation_units; t; t = TREE_CHAIN (t))
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
-
-  /* Now do the same for the externals scope.  */
-  t = pop_scope ();
-  if (t)
-    c_write_global_declarations_1 (BLOCK_VARS (t));
+  c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+
+  /* Generate functions to call static constructors and destructors
+     for targets that do not support .ctors/.dtors sections.  These
+     functions have magic names which are detected by collect2.  */
+  build_cdtor ('I', static_ctors); static_ctors = 0;
+  build_cdtor ('D', static_dtors); static_dtors = 0;
+
+  /* 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"