]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/c/c-decl.c
Implement -Wimplicit-fallthrough.
[thirdparty/gcc.git] / gcc / c / c-decl.c
index 6aac8c36157751814a46735c03352f6bb10d7121..9e32be2e8ed1be7eab8ab3cf5d86524a6b4913e7 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988-2015 Free Software Foundation, Inc.
+   Copyright (C) 1988-2016 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -27,44 +27,32 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "target.h"
+#include "function.h"
+#include "c-tree.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "cgraph.h"
 #include "intl.h"
-#include "symtab.h"
-#include "alias.h"
-#include "tree.h"
-#include "fold-const.h"
 #include "print-tree.h"
 #include "stor-layout.h"
 #include "varasm.h"
 #include "attribs.h"
-#include "stringpool.h"
-#include "tree-inline.h"
-#include "flags.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "c-tree.h"
 #include "toplev.h"
-#include "tm_p.h"
-#include "cpplib.h"
-#include "target.h"
 #include "debug.h"
-#include "opts.h"
-#include "timevar.h"
-#include "c-family/c-common.h"
 #include "c-family/c-objc.h"
 #include "c-family/c-pragma.h"
 #include "c-family/c-ubsan.h"
 #include "c-lang.h"
 #include "langhooks.h"
 #include "tree-iterator.h"
-#include "diagnostic-core.h"
 #include "dumpfile.h"
-#include "cgraph.h"
-#include "langhooks-def.h"
 #include "plugin.h"
 #include "c-family/c-ada-spec.h"
 #include "cilk.h"
 #include "builtins.h"
+#include "spellcheck-tree.h"
+#include "gcc-rich-location.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -586,15 +574,15 @@ struct c_struct_parse_info
 {
   /* If warn_cxx_compat, a list of types defined within this
      struct.  */
-  vec<tree> struct_types;
+  auto_vec<tree> struct_types;
   /* If warn_cxx_compat, a list of field names which have bindings,
      and which are defined in this struct, but which are not defined
      in any enclosing struct.  This is used to clear the in_struct
      field of the c_bindings structure.  */
-  vec<c_binding_ptr> fields;
+  auto_vec<c_binding_ptr> fields;
   /* If warn_cxx_compat, a list of typedef names used when defining
      fields in this struct.  */
-  vec<tree> typedefs_seen;
+  auto_vec<tree> typedefs_seen;
 };
 
 /* Information for the struct or union currently being parsed, or
@@ -1340,7 +1328,7 @@ pop_scope (void)
                set_type_context (TREE_TYPE (p), context);
            }
 
-         /* Fall through.  */
+         gcc_fallthrough ();
          /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
             already been put there by store_parm_decls.  Unused-
             parameter warnings are handled by function.c.
@@ -1660,7 +1648,19 @@ match_builtin_function_types (tree newtype, tree oldtype)
     }
 
   trytype = build_function_type (newrettype, tryargs);
-  return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
+
+  /* Allow declaration to change transaction_safe attribute.  */
+  tree oldattrs = TYPE_ATTRIBUTES (oldtype);
+  tree oldtsafe = lookup_attribute ("transaction_safe", oldattrs);
+  tree newattrs = TYPE_ATTRIBUTES (newtype);
+  tree newtsafe = lookup_attribute ("transaction_safe", newattrs);
+  if (oldtsafe && !newtsafe)
+    oldattrs = remove_attribute ("transaction_safe", oldattrs);
+  else if (newtsafe && !oldtsafe)
+    oldattrs = tree_cons (get_identifier ("transaction_safe"),
+                         NULL_TREE, oldattrs);
+
+  return build_type_attribute_variant (trytype, oldattrs);
 }
 
 /* Subroutine of diagnose_mismatched_decls.  Check for function type
@@ -2229,43 +2229,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
-      if (DECL_DECLARED_INLINE_P (newdecl)
-         && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "inline declaration of %qD follows "
-                          "declaration with attribute noinline", newdecl);
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "noinline follows inline declaration ", newdecl);
-      else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "%qs follows declaration with attribute %qs",
-                          newdecl, "noinline", "always_inline");
-      else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute "
-                          "%qs follows declaration with attribute %qs",
-                          newdecl, "always_inline", "noinline");
-      else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute %qs follows "
-                          "declaration with attribute %qs", newdecl, "cold",
-                          "hot");
-      else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
-              && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
-       warned |= warning (OPT_Wattributes,
-                          "declaration of %q+D with attribute %qs follows "
-                          "declaration with attribute %qs", newdecl, "hot",
-                          "cold");
-    }
+    warned |= diagnose_mismatched_attributes (olddecl, newdecl);
   else /* PARM_DECL, VAR_DECL */
     {
       /* Redeclaration of a parameter is a constraint violation (this is
@@ -2360,6 +2324,35 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
   DECL_ATTRIBUTES (newdecl)
     = targetm.merge_decl_attributes (olddecl, newdecl);
 
+  /* For typedefs use the old type, as the new type's DECL_NAME points
+     at newdecl, which will be ggc_freed.  */
+  if (TREE_CODE (newdecl) == TYPE_DECL)
+    {
+      /* But NEWTYPE might have an attribute, honor that.  */
+      tree tem = newtype;
+      newtype = oldtype;
+
+      if (TYPE_USER_ALIGN (tem))
+       {
+         if (TYPE_ALIGN (tem) > TYPE_ALIGN (newtype))
+           SET_TYPE_ALIGN (newtype, TYPE_ALIGN (tem));
+         TYPE_USER_ALIGN (newtype) = true;
+       }
+
+      /* And remove the new type from the variants list.  */
+      if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
+       {
+         tree remove = TREE_TYPE (newdecl);
+         for (tree t = TYPE_MAIN_VARIANT (remove); ;
+              t = TYPE_NEXT_VARIANT (t))
+           if (TYPE_NEXT_VARIANT (t) == remove)
+             {
+               TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+               break;
+             }
+       }
+    }
+
   /* Merge the data types specified in the two decls.  */
   TREE_TYPE (newdecl)
     = TREE_TYPE (olddecl)
@@ -2383,7 +2376,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       DECL_MODE (newdecl) = DECL_MODE (olddecl);
       if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
        {
-         DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+         SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl));
          DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
        }
     }
@@ -2922,7 +2915,8 @@ pushdecl (tree x)
        }
       if (scope != file_scope
          && !DECL_IN_SYSTEM_HEADER (x))
-       warning (OPT_Wnested_externs, "nested extern declaration of %qD", x);
+       warning_at (locus, OPT_Wnested_externs,
+                   "nested extern declaration of %qD", x);
 
       while (b && !B_IN_EXTERNAL_SCOPE (b))
        {
@@ -3050,8 +3044,7 @@ pushdecl (tree x)
        element = TREE_TYPE (element);
       element = TYPE_MAIN_VARIANT (element);
 
-      if ((TREE_CODE (element) == RECORD_TYPE
-          || TREE_CODE (element) == UNION_TYPE)
+      if (RECORD_OR_UNION_TYPE_P (element)
          && (TREE_CODE (x) != TYPE_DECL
              || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
          && !COMPLETE_TYPE_P (element))
@@ -3095,13 +3088,36 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
   if (warn_implicit_function_declaration)
     {
       bool warned;
+      const char *hint = NULL;
+      if (!olddecl)
+       hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME);
 
       if (flag_isoc99)
-       warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
-                         "implicit declaration of function %qE", id);
+       if (hint)
+         {
+           gcc_rich_location richloc (loc);
+           richloc.add_fixit_replace (hint);
+           warned = pedwarn_at_rich_loc
+             (&richloc, OPT_Wimplicit_function_declaration,
+              "implicit declaration of function %qE; did you mean %qs?",
+              id, hint);
+         }
+       else
+         warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
+                           "implicit declaration of function %qE", id);
       else
-       warned = warning_at (loc, OPT_Wimplicit_function_declaration,
-                            G_("implicit declaration of function %qE"), id);
+       if (hint)
+         {
+           gcc_rich_location richloc (loc);
+           richloc.add_fixit_replace (hint);
+           warned = warning_at_rich_loc
+             (&richloc, OPT_Wimplicit_function_declaration,
+              G_("implicit declaration of function %qE;did you mean %qs?"),
+              id, hint);
+         }
+       else
+         warned = warning_at (loc, OPT_Wimplicit_function_declaration,
+                              G_("implicit declaration of function %qE"), id);
       if (olddecl && warned)
        locate_old_decl (olddecl);
     }
@@ -3311,7 +3327,7 @@ implicitly_declare (location_t loc, tree functionid)
 
   if (decl)
     {
-      if (decl == error_mark_node)
+      if (TREE_CODE (decl) != FUNCTION_DECL)
        return decl;
 
       /* FIXME: Objective-C has weird not-really-builtin functions
@@ -3417,13 +3433,38 @@ undeclared_variable (location_t loc, tree id)
 
   if (current_function_decl == 0)
     {
-      error_at (loc, "%qE undeclared here (not in a function)", id);
+      const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+      if (guessed_id)
+       {
+         gcc_rich_location richloc (loc);
+         richloc.add_fixit_replace (guessed_id);
+         error_at_rich_loc (&richloc,
+                            "%qE undeclared here (not in a function);"
+                            " did you mean %qs?",
+                            id, guessed_id);
+       }
+      else
+       error_at (loc, "%qE undeclared here (not in a function)", id);
       scope = current_scope;
     }
   else
     {
       if (!objc_diagnose_private_ivar (id))
-        error_at (loc, "%qE undeclared (first use in this function)", id);
+       {
+         const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+         if (guessed_id)
+           {
+             gcc_rich_location richloc (loc);
+             richloc.add_fixit_replace (guessed_id);
+             error_at_rich_loc
+               (&richloc,
+                "%qE undeclared (first use in this function);"
+                " did you mean %qs?",
+                id, guessed_id);
+           }
+         else
+           error_at (loc, "%qE undeclared (first use in this function)", id);
+       }
       if (!already)
        {
           inform (loc, "each undeclared identifier is reported only"
@@ -3475,7 +3516,7 @@ lookup_label (tree name)
   if (current_function_scope == 0)
     {
       error ("label %qE referenced outside of any function", name);
-      return 0;
+      return NULL_TREE;
     }
 
   /* Use a label already defined or ref'd with this name, but not if
@@ -3812,14 +3853,14 @@ c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings,
    If the wrong kind of type is found, an error is reported.  */
 
 static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only,
+lookup_tag (enum tree_code code, tree name, bool thislevel_only,
            location_t *ploc)
 {
   struct c_binding *b = I_TAG_BINDING (name);
-  int thislevel = 0;
+  bool thislevel = false;
 
   if (!b || !b->decl)
-    return 0;
+    return NULL_TREE;
 
   /* We only care about whether it's in this level if
      thislevel_only was set or it might be a type clash.  */
@@ -3831,11 +3872,11 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only,
         file scope is created.)  */
       if (B_IN_CURRENT_SCOPE (b)
          || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
-       thislevel = 1;
+       thislevel = true;
     }
 
   if (thislevel_only && !thislevel)
-    return 0;
+    return NULL_TREE;
 
   if (TREE_CODE (b->decl) != code)
     {
@@ -3857,6 +3898,18 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only,
   return b->decl;
 }
 
+/* Return true if a definition exists for NAME with code CODE.  */
+
+bool
+tag_exists_p (enum tree_code code, tree name)
+{
+  struct c_binding *b = I_TAG_BINDING (name);
+
+  if (b == NULL || b->decl == NULL_TREE)
+    return false;
+  return TREE_CODE (b->decl) == code;
+}
+
 /* Print an error message now
    for a recent invalid struct, union or enum cross reference.
    We don't print them immediately because they are not invalid
@@ -3886,7 +3939,7 @@ lookup_name (tree name)
       maybe_record_typedef_use (b->decl);
       return b->decl;
     }
-  return 0;
+  return NULL_TREE;
 }
 
 /* Similar to `lookup_name' but look only at the indicated scope.  */
@@ -3899,8 +3952,121 @@ lookup_name_in_scope (tree name, struct c_scope *scope)
   for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
     if (B_IN_SCOPE (b, scope))
       return b->decl;
-  return 0;
+  return NULL_TREE;
 }
+
+/* Look for the closest match for NAME within the currently valid
+   scopes.
+
+   This finds the identifier with the lowest Levenshtein distance to
+   NAME.  If there are multiple candidates with equal minimal distance,
+   the first one found is returned.  Scopes are searched from innermost
+   outwards, and within a scope in reverse order of declaration, thus
+   benefiting candidates "near" to the current scope.
+
+   The function also looks for similar macro names to NAME, since a
+   misspelled macro name will not be expanded, and hence looks like an
+   identifier to the C frontend.
+
+   It also looks for start_typename keywords, to detect "singed" vs "signed"
+   typos.  */
+
+const char *
+lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
+{
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+
+  best_match<tree, tree> bm (name);
+
+  /* Look within currently valid scopes.  */
+  for (c_scope *scope = current_scope; scope; scope = scope->outer)
+    for (c_binding *binding = scope->bindings; binding; binding = binding->prev)
+      {
+       if (!binding->id || binding->invisible)
+         continue;
+       /* Don't use bindings from implicitly declared functions,
+          as they were likely misspellings themselves.  */
+       if (TREE_CODE (binding->decl) == FUNCTION_DECL)
+         if (C_DECL_IMPLICIT (binding->decl))
+           continue;
+       switch (kind)
+         {
+         case FUZZY_LOOKUP_TYPENAME:
+           if (TREE_CODE (binding->decl) != TYPE_DECL)
+             continue;
+           break;
+
+         case FUZZY_LOOKUP_FUNCTION_NAME:
+           if (TREE_CODE (binding->decl) != FUNCTION_DECL)
+             {
+               /* Allow function pointers.  */
+               if ((VAR_P (binding->decl)
+                    || TREE_CODE (binding->decl) == PARM_DECL)
+                   && TREE_CODE (TREE_TYPE (binding->decl)) == POINTER_TYPE
+                   && (TREE_CODE (TREE_TYPE (TREE_TYPE (binding->decl)))
+                       == FUNCTION_TYPE))
+                 break;
+               continue;
+             }
+           break;
+
+         default:
+           break;
+         }
+       bm.consider (binding->id);
+      }
+
+  /* Consider macros: if the user misspelled a macro name e.g. "SOME_MACRO"
+     as:
+       x = SOME_OTHER_MACRO (y);
+     then "SOME_OTHER_MACRO" will survive to the frontend and show up
+     as a misspelled identifier.
+
+     Use the best distance so far so that a candidate is only set if
+     a macro is better than anything so far.  This allows early rejection
+     (without calculating the edit distance) of macro names that must have
+     distance >= bm.get_best_distance (), and means that we only get a
+     non-NULL result for best_macro_match if it's better than any of
+     the identifiers already checked, which avoids needless creation
+     of identifiers for macro hashnodes.  */
+  best_macro_match bmm (name, bm.get_best_distance (), parse_in);
+  cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate ();
+  /* If a macro is the closest so far to NAME, use it, creating an
+     identifier tree node for it.  */
+  if (best_macro)
+    {
+      const char *id = (const char *)best_macro->ident.str;
+      tree macro_as_identifier
+       = get_identifier_with_length (id, best_macro->ident.len);
+      bm.set_best_so_far (macro_as_identifier,
+                         bmm.get_best_distance (),
+                         bmm.get_best_candidate_length ());
+    }
+
+  /* Try the "start_typename" keywords to detect
+     "singed" vs "signed" typos.  */
+  if (kind == FUZZY_LOOKUP_TYPENAME)
+    {
+      for (unsigned i = 0; i < num_c_common_reswords; i++)
+       {
+         const c_common_resword *resword = &c_common_reswords[i];
+         if (!c_keyword_starts_typename (resword->rid))
+           continue;
+         tree resword_identifier = ridpointers [resword->rid];
+         if (!resword_identifier)
+           continue;
+         gcc_assert (TREE_CODE (resword_identifier) == IDENTIFIER_NODE);
+         bm.consider (resword_identifier);
+       }
+    }
+
+  tree best = bm.get_best_meaningful_candidate ();
+  if (best)
+    return IDENTIFIER_POINTER (best);
+  else
+    return NULL;
+}
+
 \f
 /* Create the predefined scalar types of C,
    and some nodes representing standard constants (0, 1, (void *) 0).
@@ -3986,7 +4152,7 @@ c_make_fname_decl (location_t loc, tree id, int type_dep)
         the __FUNCTION__ is believed to appear in K&R style function
         parameter declarator.  In that case we still don't have
         function_scope.  */
-      && (!seen_error () || current_function_scope))
+      && current_function_scope)
     {
       DECL_CONTEXT (decl) = current_function_decl;
       bind (id, decl, current_function_scope,
@@ -4139,9 +4305,9 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
          else
            {
              pending_invalid_xref = 0;
-             t = lookup_tag (code, name, 1, NULL);
+             t = lookup_tag (code, name, true, NULL);
 
-             if (t == 0)
+             if (t == NULL_TREE)
                {
                  t = make_node (code);
                  pushtag (input_location, name, t);
@@ -4394,13 +4560,7 @@ c_decl_attributes (tree *node, tree attributes, int flags)
          || TREE_CODE (*node) == FUNCTION_DECL))
     {
       if (VAR_P (*node)
-         && ((DECL_CONTEXT (*node)
-              && TREE_CODE (DECL_CONTEXT (*node)) == FUNCTION_DECL)
-             || (current_function_decl && !DECL_EXTERNAL (*node))))
-       error ("%q+D in block scope inside of declare target directive",
-              *node);
-      else if (VAR_P (*node)
-              && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
+         && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
        error ("%q+D in declare target directive does not have mappable type",
               *node);
       else
@@ -4639,8 +4799,7 @@ diagnose_uninitialized_cst_member (tree decl, tree type)
          inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
        }
 
-      if (TREE_CODE (field_type) == RECORD_TYPE
-         || TREE_CODE (field_type) == UNION_TYPE)
+      if (RECORD_OR_UNION_TYPE_P (field_type))
        diagnose_uninitialized_cst_member (decl, field_type);
     }
 }
@@ -4741,7 +4900,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
              struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
              while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
                b_ext = b_ext->shadowed;
-             if (b_ext)
+             if (b_ext && TREE_CODE (decl) == TREE_CODE (b_ext->decl))
                {
                  if (b_ext->u.type && comptypes (b_ext->u.type, type))
                    b_ext->u.type = composite_type (b_ext->u.type, type);
@@ -4789,6 +4948,12 @@ finish_decl (tree decl, location_t init_loc, tree init,
           TREE_TYPE (decl) = error_mark_node;
         }
 
+      if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+         || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+         && DECL_SIZE (decl) == NULL_TREE
+         && TREE_STATIC (decl))
+       incomplete_record_decls.safe_push (decl);
+
       if (is_global_var (decl) && DECL_SIZE (decl) != 0)
        {
          if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
@@ -4937,7 +5102,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
          vec<tree, va_gc> *v;
 
          /* Build "cleanup(&decl)" for the destructor.  */
-         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, false);
          vec_alloc (v, 1);
          v->quick_push (cleanup);
          cleanup = c_build_function_call_vec (DECL_SOURCE_LOCATION (decl),
@@ -4962,8 +5127,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
       if (TREE_READONLY (decl))
        warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
                    "uninitialized const %qD is invalid in C++", decl);
-      else if ((TREE_CODE (type) == RECORD_TYPE
-               || TREE_CODE (type) == UNION_TYPE)
+      else if (RECORD_OR_UNION_TYPE_P (type)
               && C_TYPE_FIELDS_READONLY (type))
        diagnose_uninitialized_cst_member (decl, type);
     }
@@ -5075,7 +5239,7 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
 
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     {
-      c_incomplete_type_error (NULL_TREE, type);
+      c_incomplete_type_error (loc, NULL_TREE, type);
       return error_mark_node;
     }
 
@@ -5154,8 +5318,10 @@ flexible_array_type_p (tree type)
 \f
 /* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
    replacing with appropriate values if they are invalid.  */
+
 static void
-check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
+check_bitfield_type_and_width (location_t loc, tree *type, tree *width,
+                              tree orig_name)
 {
   tree type_mv;
   unsigned int max_width;
@@ -5168,7 +5334,7 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
      field widths.  */
   if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
     {
-      error ("bit-field %qs width not an integer constant", name);
+      error_at (loc, "bit-field %qs width not an integer constant", name);
       *width = integer_one_node;
     }
   else
@@ -5177,24 +5343,24 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
        {
          *width = c_fully_fold (*width, false, NULL);
          if (TREE_CODE (*width) == INTEGER_CST)
-           pedwarn (input_location, OPT_Wpedantic,
+           pedwarn (loc, OPT_Wpedantic,
                     "bit-field %qs width not an integer constant expression",
                     name);
        }
       if (TREE_CODE (*width) != INTEGER_CST)
        {
-         error ("bit-field %qs width not an integer constant", name);
+         error_at (loc, "bit-field %qs width not an integer constant", name);
          *width = integer_one_node;
        }
       constant_expression_warning (*width);
       if (tree_int_cst_sgn (*width) < 0)
        {
-         error ("negative width in bit-field %qs", name);
+         error_at (loc, "negative width in bit-field %qs", name);
          *width = integer_one_node;
        }
       else if (integer_zerop (*width) && orig_name)
        {
-         error ("zero width for bit-field %qs", name);
+         error_at (loc, "zero width for bit-field %qs", name);
          *width = integer_one_node;
        }
     }
@@ -5204,7 +5370,7 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
       && TREE_CODE (*type) != BOOLEAN_TYPE
       && TREE_CODE (*type) != ENUMERAL_TYPE)
     {
-      error ("bit-field %qs has invalid type", name);
+      error_at (loc, "bit-field %qs has invalid type", name);
       *type = unsigned_type_node;
     }
 
@@ -5213,14 +5379,14 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
       && type_mv != integer_type_node
       && type_mv != unsigned_type_node
       && type_mv != boolean_type_node)
-    pedwarn_c90 (input_location, OPT_Wpedantic,
+    pedwarn_c90 (loc, OPT_Wpedantic,
                 "type of bit-field %qs is a GCC extension", name);
 
   max_width = TYPE_PRECISION (*type);
 
   if (0 < compare_tree_int (*width, max_width))
     {
-      error ("width of %qs exceeds its type", name);
+      error_at (loc, "width of %qs exceeds its type", name);
       w = max_width;
       *width = build_int_cst (integer_type_node, w);
     }
@@ -5233,7 +5399,7 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
       if (!lt
          || w < tree_int_cst_min_precision (lt->enum_min, TYPE_SIGN (*type))
          || w < tree_int_cst_min_precision (lt->enum_max, TYPE_SIGN (*type)))
-       warning (0, "%qs is narrower than values of its type", name);
+       warning_at (loc, 0, "%qs is narrower than values of its type", name);
     }
 }
 
@@ -5272,9 +5438,10 @@ warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
+  rich_location richloc (line_table, location);
 
   va_start (ap, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
                        flag_isoc99 ? DK_PEDWARN : DK_WARNING);
   diagnostic.option_index = opt;
   report_diagnostic (&diagnostic);
@@ -5347,10 +5514,11 @@ grokdeclarator (const struct c_declarator *declarator,
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
   tree element_type;
+  tree orig_qual_type = NULL;
+  size_t orig_qual_indirect = 0;
   struct c_arg_info *arg_info = 0;
   addr_space_t as1, as2, address_space;
   location_t loc = UNKNOWN_LOCATION;
-  const char *errmsg;
   tree expr_dummy;
   bool expr_const_operands_dummy;
   enum c_declarator_kind first_non_attr_kind;
@@ -5385,9 +5553,9 @@ grokdeclarator (const struct c_declarator *declarator,
        case cdk_function:
        case cdk_pointer:
          funcdef_syntax = (decl->kind == cdk_function);
-         decl = decl->declarator;
          if (first_non_attr_kind == cdk_attrs)
            first_non_attr_kind = decl->kind;
+         decl = decl->declarator;
          break;
 
        case cdk_attrs:
@@ -5509,12 +5677,17 @@ grokdeclarator (const struct c_declarator *declarator,
   if ((TREE_CODE (type) == ARRAY_TYPE
        || first_non_attr_kind == cdk_array)
       && TYPE_QUALS (element_type))
-    type = TYPE_MAIN_VARIANT (type);
+    {
+      orig_qual_type = type;
+      type = TYPE_MAIN_VARIANT (type);
+    }
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
                | (restrictp ? TYPE_QUAL_RESTRICT : 0)
                | (volatilep ? TYPE_QUAL_VOLATILE : 0)
                | (atomicp ? TYPE_QUAL_ATOMIC : 0)
                | ENCODE_QUAL_ADDR_SPACE (address_space));
+  if (type_quals != TYPE_QUALS (element_type))
+    orig_qual_type = NULL_TREE;
 
   /* Applying the _Atomic qualifier to an array type (through the use
      of typedefs or typeof) must be detected here.  If the qualifier
@@ -5752,10 +5925,21 @@ grokdeclarator (const struct c_declarator *declarator,
                  {
                    if (name)
                      error_at (loc, "size of array %qE has non-integer type",
-                               name);
+                               name);
                    else
                      error_at (loc,
-                               "size of unnamed array has non-integer type");
+                               "size of unnamed array has non-integer type");
+                   size = integer_one_node;
+                 }
+               /* This can happen with enum forward declaration.  */
+               else if (!COMPLETE_TYPE_P (TREE_TYPE (size)))
+                 {
+                   if (name)
+                     error_at (loc, "size of array %qE has incomplete type",
+                               name);
+                   else
+                     error_at (loc, "size of unnamed array has incomplete "
+                               "type");
                    size = integer_one_node;
                  }
 
@@ -5940,6 +6124,18 @@ grokdeclarator (const struct c_declarator *declarator,
              {
                error_at (loc, "array type has incomplete element type %qT",
                          type);
+               /* See if we can be more helpful.  */
+               if (TREE_CODE (type) == ARRAY_TYPE)
+                 {
+                   if (name)
+                     inform (loc, "declaration of %qE as multidimensional "
+                             "array must have bounds for all dimensions "
+                             "except the first", name);
+                   else
+                     inform (loc, "declaration of multidimensional array "
+                             "must have bounds for all dimensions except "
+                             "the first");
+                 }
                type = error_mark_node;
              }
            else
@@ -5993,6 +6189,9 @@ grokdeclarator (const struct c_declarator *declarator,
                    TYPE_SIZE_UNIT (type) = size_zero_node;
                    SET_TYPE_STRUCTURAL_EQUALITY (type);
                  }
+
+               if (!valid_array_size_p (loc, type, name))
+                 type = error_mark_node;
              }
 
            if (decl_context != PARM
@@ -6000,11 +6199,13 @@ grokdeclarator (const struct c_declarator *declarator,
                    || array_ptr_attrs != NULL_TREE
                    || array_parm_static))
              {
-               error_at (loc, "static or type qualifiers in non-parameter array declarator");
+               error_at (loc, "static or type qualifiers in non-parameter "
+                         "array declarator");
                array_ptr_quals = TYPE_UNQUALIFIED;
                array_ptr_attrs = NULL_TREE;
                array_parm_static = 0;
              }
+           orig_qual_indirect++;
            break;
          }
        case cdk_function:
@@ -6014,6 +6215,7 @@ grokdeclarator (const struct c_declarator *declarator,
               attributes.  */
            bool really_funcdef = false;
            tree arg_types;
+           orig_qual_type = NULL_TREE;
            if (funcdef_flag)
              {
                const struct c_declarator *t = declarator->declarator;
@@ -6050,12 +6252,6 @@ grokdeclarator (const struct c_declarator *declarator,
                            "an array");
                type = integer_type_node;
              }
-           errmsg = targetm.invalid_return_type (type);
-           if (errmsg)
-             {
-               error (errmsg);
-               type = integer_type_node;
-             }
 
            /* Construct the function type and go to the next
               inner layer of declarator.  */
@@ -6066,20 +6262,35 @@ grokdeclarator (const struct c_declarator *declarator,
               qualify the return type, not the function type.  */
            if (type_quals)
              {
+               int quals_used = type_quals;
                /* 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)
+                  them for noreturn functions.  The resolution of C11
+                  DR#423 means qualifiers (other than _Atomic) are
+                  actually removed from the return type when
+                  determining the function type.  */
+               if (flag_isoc11)
+                 quals_used &= TYPE_QUAL_ATOMIC;
+               if (quals_used && VOID_TYPE_P (type) && really_funcdef)
                  pedwarn (loc, 0,
                           "function definition has qualified void return type");
                else
                  warning_at (loc, OPT_Wignored_qualifiers,
                           "type qualifiers ignored on function return type");
 
-               type = c_build_qualified_type (type, type_quals);
+               /* Ensure an error for restrict on invalid types; the
+                  DR#423 resolution is not entirely clear about
+                  this.  */
+               if (flag_isoc11
+                   && (type_quals & TYPE_QUAL_RESTRICT)
+                   && (!POINTER_TYPE_P (type)
+                       || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+                 error_at (loc, "invalid use of %<restrict%>");
+               if (quals_used)
+                 type = c_build_qualified_type (type, quals_used);
              }
            type_quals = TYPE_UNQUALIFIED;
 
@@ -6114,7 +6325,9 @@ grokdeclarator (const struct c_declarator *declarator,
              pedwarn (loc, OPT_Wpedantic,
                       "ISO C forbids qualified function types");
            if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
+             type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                            orig_qual_indirect);
+           orig_qual_type = NULL_TREE;
            size_varies = false;
 
            /* When the pointed-to type involves components of variable size,
@@ -6225,16 +6438,16 @@ grokdeclarator (const struct c_declarator *declarator,
   /* Check the type and width of a bit-field.  */
   if (bitfield)
     {
-      check_bitfield_type_and_width (&type, width, name);
+      check_bitfield_type_and_width (loc, &type, width, name);
       /* C11 makes it implementation-defined (6.7.2.1#5) whether
         atomic types are permitted for bit-fields; we have no code to
         make bit-field accesses atomic, so disallow them.  */
       if (type_quals & TYPE_QUAL_ATOMIC)
        {
          if (name)
-           error ("bit-field %qE has atomic type", name);
+           error_at (loc, "bit-field %qE has atomic type", name);
          else
-           error ("bit-field has atomic type");
+           error_at (loc, "bit-field has atomic type");
          type_quals &= ~TYPE_QUAL_ATOMIC;
        }
     }
@@ -6263,7 +6476,7 @@ grokdeclarator (const struct c_declarator *declarator,
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        error_at (loc, "alignment specified for function %qE", name);
-      else if (declspecs->align_log != -1)
+      else if (declspecs->align_log != -1 && TYPE_P (type))
        {
          alignas_align = 1U << declspecs->align_log;
          if (alignas_align < min_align_of_type (type))
@@ -6279,22 +6492,6 @@ grokdeclarator (const struct c_declarator *declarator,
        }
     }
 
-  /* Did array size calculations overflow or does the array cover more
-     than half of the address-space?  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && COMPLETE_TYPE_P (type)
-      && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
-      && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
-    {
-      if (name)
-       error_at (loc, "size of array %qE is too large", name);
-      else
-       error_at (loc, "size of unnamed array is too large");
-      /* If we proceed with the array type as it is, we'll eventually
-        crash in tree_to_[su]hwi().  */
-      type = error_mark_node;
-    }
-
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
 
   if (storage_class == csc_typedef)
@@ -6312,7 +6509,8 @@ grokdeclarator (const struct c_declarator *declarator,
        pedwarn (loc, OPT_Wpedantic,
                 "ISO C forbids qualified function types");
       if (type_quals)
-       type = c_build_qualified_type (type, type_quals);
+       type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                      orig_qual_indirect);
       decl = build_decl (declarator->id_loc,
                         TYPE_DECL, declarator->u.id, type);
       if (declspecs->explicit_signed_p)
@@ -6365,7 +6563,8 @@ grokdeclarator (const struct c_declarator *declarator,
        pedwarn (loc, OPT_Wpedantic,
                 "ISO C forbids const or volatile function types");
       if (type_quals)
-       type = c_build_qualified_type (type, type_quals);
+       type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                      orig_qual_indirect);
       return type;
     }
 
@@ -6412,8 +6611,16 @@ grokdeclarator (const struct c_declarator *declarator,
          {
            /* Transfer const-ness of array into that of type pointed to.  */
            type = TREE_TYPE (type);
+           if (orig_qual_type != NULL_TREE)
+             {
+               if (orig_qual_indirect == 0)
+                 orig_qual_type = TREE_TYPE (orig_qual_type);
+               else
+                 orig_qual_indirect--;
+             }
            if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
+             type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                            orig_qual_indirect);
            type = c_build_pointer_type (type);
            type_quals = array_ptr_quals;
            if (type_quals)
@@ -6503,8 +6710,11 @@ grokdeclarator (const struct c_declarator *declarator,
            type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
            TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
                                                   NULL_TREE);
+           if (orig_qual_indirect == 0)
+             orig_qual_type = NULL_TREE;
          }
-       type = c_build_qualified_type (type, type_quals);
+       type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                      orig_qual_indirect);
        decl = build_decl (declarator->id_loc,
                           FIELD_DECL, declarator->u.id, type);
        DECL_NONADDRESSABLE_P (decl) = bitfield;
@@ -6616,7 +6826,8 @@ grokdeclarator (const struct c_declarator *declarator,
        /* An uninitialized decl with `extern' is a reference.  */
        int extern_ref = !initialized && storage_class == csc_extern;
 
-       type = c_build_qualified_type (type, type_quals);
+       type = c_build_qualified_type (type, type_quals, orig_qual_type,
+                                      orig_qual_indirect);
 
        /* C99 6.2.2p7: It is invalid (compile-time undefined
           behavior) to create an 'extern' declaration for a
@@ -6701,7 +6912,7 @@ grokdeclarator (const struct c_declarator *declarator,
     /* Apply _Alignas specifiers.  */
     if (alignas_align)
       {
-       DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+       SET_DECL_ALIGN (decl, alignas_align * BITS_PER_UNIT);
        DECL_USER_ALIGN (decl) = 1;
       }
 
@@ -6731,8 +6942,7 @@ grokdeclarator (const struct c_declarator *declarator,
        && VAR_P (decl)
        && TREE_PUBLIC (decl)
        && TREE_STATIC (decl)
-       && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
-           || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+       && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
            || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
        && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
@@ -6795,7 +7005,6 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
     {
       tree parm, type, typelt;
       unsigned int parmno;
-      const char *errmsg;
 
       /* If there is a parameter of incomplete type in a definition,
         this is an error.  In a declaration this is valid, and a
@@ -6844,15 +7053,6 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
                }
            }
 
-         errmsg = targetm.invalid_parameter_type (type);
-         if (errmsg)
-           {
-             error (errmsg);
-             TREE_VALUE (typelt) = error_mark_node;
-             TREE_TYPE (parm) = error_mark_node;
-             arg_types = NULL_TREE;
-           }
-
          if (DECL_NAME (parm) && TREE_USED (parm))
            warn_if_shadowing (parm);
        }
@@ -6898,7 +7098,6 @@ get_parm_info (bool ellipsis, tree expr)
   tree types    = 0;
   tree others   = 0;
 
-  static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
   arg_info->had_vla_unspec = current_scope->had_vla_unspec;
@@ -6923,11 +7122,11 @@ get_parm_info (bool ellipsis, tree expr)
     {
       if (TYPE_QUALS (TREE_TYPE (b->decl)) != TYPE_UNQUALIFIED
          || C_DECL_REGISTER (b->decl))
-       error ("%<void%> as only parameter may not be qualified");
+       error_at (b->locus, "%<void%> as only parameter may not be qualified");
 
       /* There cannot be an ellipsis.  */
       if (ellipsis)
-       error ("%<void%> must be the only parameter");
+       error_at (b->locus, "%<void%> must be the only parameter");
 
       arg_info->types = void_list_node;
       return arg_info;
@@ -6956,13 +7155,14 @@ get_parm_info (bool ellipsis, tree expr)
 
          /* Check for forward decls that never got their actual decl.  */
          if (TREE_ASM_WRITTEN (decl))
-           error ("parameter %q+D has just a forward declaration", decl);
+           error_at (b->locus,
+                     "parameter %q+D has just a forward declaration", decl);
          /* Check for (..., void, ...) and issue an error.  */
          else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
            {
              if (!gave_void_only_once_err)
                {
-                 error ("%<void%> must be the only parameter");
+                 error_at (b->locus, "%<void%> must be the only parameter");
                  gave_void_only_once_err = true;
                }
            }
@@ -7001,19 +7201,16 @@ get_parm_info (bool ellipsis, tree expr)
            {
              if (b->id)
                /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning (0, "%<%s %E%> declared inside parameter list",
-                        keyword, b->id);
+               warning_at (b->locus, 0,
+                           "%<%s %E%> declared inside parameter list"
+                           " will not be visible outside of this definition or"
+                           " declaration", keyword, b->id);
              else
                /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning (0, "anonymous %s declared inside parameter list",
-                        keyword);
-
-             if (!explained_incomplete_types)
-               {
-                 warning (0, "its scope is only this definition or declaration,"
-                          " which is probably not what you want");
-                 explained_incomplete_types = true;
-               }
+               warning_at (b->locus, 0,
+                           "anonymous %s declared inside parameter list"
+                           " will not be visible outside of this definition or"
+                           " declaration", keyword);
            }
 
          tag.id = b->id;
@@ -7021,25 +7218,28 @@ get_parm_info (bool ellipsis, tree expr)
          vec_safe_push (tags, tag);
          break;
 
+       case FUNCTION_DECL:
+         /* FUNCTION_DECLs appear when there is an implicit function
+            declaration in the parameter list.  */
+         gcc_assert (b->nested || seen_error ());
+         goto set_shadowed;
+
        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.  FUNCTION_DECLs appear when there is an implicit
-            function declaration in the parameter list.  */
+            type itself.  */
 
          /* When we reinsert this decl in the function body, we need
             to reconstruct whether it was marked as nested.  */
-         gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
-                     ? b->nested
-                     : !b->nested);
+         gcc_assert (!b->nested);
          DECL_CHAIN (decl) = others;
          others = decl;
          /* fall through */
 
        case ERROR_MARK:
+       set_shadowed:
          /* error_mark_node appears here when we have an undeclared
             variable.  Just throw it away.  */
          if (b->id)
@@ -7085,7 +7285,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name)
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
-  ref = lookup_tag (code, name, 0, &refloc);
+  ref = lookup_tag (code, name, false, &refloc);
   /* If this is the right type of tag, return what we found.
      (This reference will be shadowed by shadow_tag later if appropriate.)
      If this is the wrong type of tag, do not return it.  If it was the
@@ -7144,7 +7344,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name)
       /* Give the type a default layout like unsigned int
         to avoid crashing if it does not get defined.  */
       SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
-      TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+      SET_TYPE_ALIGN (ref, TYPE_ALIGN (unsigned_type_node));
       TYPE_USER_ALIGN (ref) = 0;
       TYPE_UNSIGNED (ref) = 1;
       TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
@@ -7189,7 +7389,7 @@ start_struct (location_t loc, enum tree_code code, tree name,
   location_t refloc = UNKNOWN_LOCATION;
 
   if (name != NULL_TREE)
-    ref = lookup_tag (code, name, 1, &refloc);
+    ref = lookup_tag (code, name, true, &refloc);
   if (ref && TREE_CODE (ref) == code)
     {
       if (TYPE_SIZE (ref))
@@ -7226,13 +7426,11 @@ start_struct (location_t loc, enum tree_code code, tree name,
     }
 
   C_TYPE_BEING_DEFINED (ref) = 1;
-  TYPE_PACKED (ref) = flag_pack_struct;
+  for (tree v = TYPE_MAIN_VARIANT (ref); v; v = TYPE_NEXT_VARIANT (v))
+    TYPE_PACKED (v) = flag_pack_struct;
 
   *enclosing_struct_parse_info = struct_parse_info;
-  struct_parse_info = XNEW (struct c_struct_parse_info);
-  struct_parse_info->struct_types.create (0);
-  struct_parse_info->fields.create (0);
-  struct_parse_info->typedefs_seen.create (0);
+  struct_parse_info = new c_struct_parse_info ();
 
   /* FIXME: This will issue a warning for a use of a type defined
      within a statement expr used within sizeof, et. al.  This is not
@@ -7291,8 +7489,7 @@ grokfield (location_t loc,
         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 type_ok = RECORD_OR_UNION_TYPE_P (type);
       bool ok = false;
 
       if (type_ok
@@ -7368,7 +7565,7 @@ is_duplicate_field (tree x, tree y)
       xt = TREE_TYPE (x);
       if (DECL_NAME (x) != NULL_TREE)
        xn = DECL_NAME (x);
-      else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
+      else if (RECORD_OR_UNION_TYPE_P (xt)
               && TYPE_NAME (xt) != NULL_TREE
               && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
        xn = DECL_NAME (TYPE_NAME (xt));
@@ -7378,7 +7575,7 @@ is_duplicate_field (tree x, tree y)
       yt = TREE_TYPE (y);
       if (DECL_NAME (y) != NULL_TREE)
        yn = DECL_NAME (y);
-      else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
+      else if (RECORD_OR_UNION_TYPE_P (yt)
               && TYPE_NAME (yt) != NULL_TREE
               && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
        yn = DECL_NAME (TYPE_NAME (yt));
@@ -7413,8 +7610,7 @@ detect_field_duplicates_hash (tree fieldlist,
          }
        *slot = y;
       }
-    else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-            || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+    else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
       {
        detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
 
@@ -7465,8 +7661,7 @@ detect_field_duplicates (tree fieldlist)
   do {
     timeout--;
     if (DECL_NAME (x) == NULL_TREE
-       && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-           || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+       && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
       timeout = 0;
     x = DECL_CHAIN (x);
   } while (timeout > 0 && x);
@@ -7482,8 +7677,7 @@ detect_field_duplicates (tree fieldlist)
        if (DECL_NAME (x)
            || (flag_plan9_extensions
                && DECL_NAME (x) == NULL_TREE
-               && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-                   || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+               && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))
                && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
                && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
          {
@@ -7596,9 +7790,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
        {
          if (DECL_NAME (x) != 0)
            break;
-         if (flag_isoc11
-             && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-                 || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+         if (flag_isoc11 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
            break;
        }
 
@@ -7643,8 +7835,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
        {
          /* A field that is pseudo-const makes the structure likewise.  */
          tree t1 = strip_array_types (TREE_TYPE (x));
-         if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
-             && C_TYPE_FIELDS_READONLY (t1))
+         if (RECORD_OR_UNION_TYPE_P (t1) && C_TYPE_FIELDS_READONLY (t1))
            C_TYPE_FIELDS_READONLY (t) = 1;
        }
 
@@ -7691,7 +7882,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
          else if (!saw_named_field)
            {
              error_at (DECL_SOURCE_LOCATION (x),
-                       "flexible array member in otherwise empty struct");
+                       "flexible array member in a struct with no named "
+                       "members");
              TREE_TYPE (x) = error_mark_node;
            }
        }
@@ -7702,8 +7894,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
                 "invalid use of structure with flexible array member");
 
       if (DECL_NAME (x)
-         || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-         || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+         || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
        saw_named_field = 1;
     }
 
@@ -7714,6 +7905,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 
   TYPE_FIELDS (t) = fieldlist;
 
+  maybe_apply_pragma_scalar_storage_order (t);
+
   layout_type (t);
 
   if (TYPE_SIZE_UNIT (t)
@@ -7722,27 +7915,45 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       && !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
     error ("type %qT is too large", t);
 
-  /* Give bit-fields their proper types.  */
-  {
-    tree *fieldlistp = &fieldlist;
-    while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
-         && TREE_TYPE (*fieldlistp) != error_mark_node)
+  /* Give bit-fields their proper types and rewrite the type of array fields
+     with scalar component if the enclosing type has reverse storage order.  */
+  for (tree field = fieldlist; field; field = DECL_CHAIN (field))
+    {
+      if (TREE_CODE (field) == FIELD_DECL
+         && DECL_INITIAL (field)
+         && TREE_TYPE (field) != error_mark_node)
        {
          unsigned HOST_WIDE_INT width
-           = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
-         tree type = TREE_TYPE (*fieldlistp);
+           = tree_to_uhwi (DECL_INITIAL (field));
+         tree type = TREE_TYPE (field);
          if (width != TYPE_PRECISION (type))
            {
-             TREE_TYPE (*fieldlistp)
+             TREE_TYPE (field)
                = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
-             DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+             DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
            }
-         DECL_INITIAL (*fieldlistp) = 0;
+         DECL_INITIAL (field) = 0;
        }
-      else
-       fieldlistp = &DECL_CHAIN (*fieldlistp);
-  }
+      else if (TYPE_REVERSE_STORAGE_ORDER (t)
+              && TREE_CODE (field) == FIELD_DECL
+              && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
+       {
+         tree ftype = TREE_TYPE (field);
+         tree ctype = strip_array_types (ftype);
+         if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode)
+           {
+             tree fmain_type = TYPE_MAIN_VARIANT (ftype);
+             tree *typep = &fmain_type;
+             do {
+               *typep = build_distinct_type_copy (*typep);
+               TYPE_REVERSE_STORAGE_ORDER (*typep) = 1;
+               typep = &TREE_TYPE (*typep);
+             } while (TREE_CODE (*typep) == ARRAY_TYPE);
+             TREE_TYPE (field)
+               = c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
+           }
+       }
+    }
 
   /* Now we have the truly final field list.
      Store it in this type and in the variants.  */
@@ -7800,6 +8011,14 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       }
   }
 
+  /* Note: C_TYPE_INCOMPLETE_VARS overloads TYPE_VFIELD which is used
+     in dwarf2out via rest_of_decl_compilation below and means
+     something totally different.  Since we will be clearing
+     C_TYPE_INCOMPLETE_VARS shortly after we iterate through them,
+     clear it ahead of time and avoid problems in dwarf2out.  Ideally,
+     C_TYPE_INCOMPLETE_VARS should use some language specific
+     node.  */
+  tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {
       TYPE_FIELDS (x) = TYPE_FIELDS (t);
@@ -7807,6 +8026,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
       C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
       C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
+      C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE;
     }
 
   /* If this was supposed to be a transparent union, but we can't
@@ -7820,17 +8040,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
     }
 
   /* If this structure or union completes the type of any previous
-     variable declaration, lay it out and output its rtl.
-
-     Note: C_TYPE_INCOMPLETE_VARS overloads TYPE_VFIELD which is used
-     in dwarf2out via rest_of_decl_compilation below and means
-     something totally different.  Since we will be clearing
-     C_TYPE_INCOMPLETE_VARS shortly after we iterate through them,
-     clear it ahead of time and avoid problems in dwarf2out.  Ideally,
-     C_TYPE_INCOMPLETE_VARS should use some language specific
-     node.  */
-  tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
-  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+     variable declaration, lay it out and output its rtl.  */
   for (x = incomplete_vars; x; x = TREE_CHAIN (x))
     {
       tree decl = TREE_VALUE (x);
@@ -7863,10 +8073,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
   if (warn_cxx_compat)
     warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
 
-  struct_parse_info->struct_types.release ();
-  struct_parse_info->fields.release ();
-  struct_parse_info->typedefs_seen.release ();
-  XDELETE (struct_parse_info);
+  delete struct_parse_info;
 
   struct_parse_info = enclosing_struct_parse_info;
 
@@ -7908,9 +8115,9 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
      forward reference.  */
 
   if (name != NULL_TREE)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
+    enumtype = lookup_tag (ENUMERAL_TYPE, name, true, &enumloc);
 
-  if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
+  if (enumtype == NULL_TREE || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
       enumtype = make_node (ENUMERAL_TYPE);
       pushtag (loc, name, enumtype);
@@ -7996,7 +8203,24 @@ finish_enum (tree enumtype, tree values, tree attributes)
   precision = MAX (tree_int_cst_min_precision (minnode, sign),
                   tree_int_cst_min_precision (maxnode, sign));
 
-  if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
+  /* If the precision of the type was specified with an attribute and it
+     was too small, give an error.  Otherwise, use it.  */
+  if (TYPE_PRECISION (enumtype) && lookup_attribute ("mode", attributes))
+    {
+      if (precision > TYPE_PRECISION (enumtype))
+       {
+         TYPE_PRECISION (enumtype) = 0;
+         error ("specified mode too small for enumeral values");
+       }
+      else
+       precision = TYPE_PRECISION (enumtype);
+    }
+  else
+    TYPE_PRECISION (enumtype) = 0;
+
+  if (TYPE_PACKED (enumtype)
+      || precision > TYPE_PRECISION (integer_type_node)
+      || TYPE_PRECISION (enumtype))
     {
       tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0);
       if (tem == NULL)
@@ -8011,19 +8235,9 @@ finish_enum (tree enumtype, tree values, tree attributes)
   TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
   TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
   TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
-  TYPE_ALIGN (enumtype) = TYPE_ALIGN (tem);
+  SET_TYPE_ALIGN (enumtype, TYPE_ALIGN (tem));
   TYPE_SIZE (enumtype) = 0;
-
-  /* If the precision of the type was specified with an attribute and it
-     was too small, give an error.  Otherwise, use it.  */
-  if (TYPE_PRECISION (enumtype)
-      && lookup_attribute ("mode", attributes))
-    {
-      if (precision > TYPE_PRECISION (enumtype))
-       error ("specified mode too small for enumeral values");
-    }
-  else
-    TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+  TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
 
   layout_type (enumtype);
 
@@ -8083,7 +8297,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
       TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
       SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
-      TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+      SET_TYPE_ALIGN (tem, TYPE_ALIGN (enumtype));
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
       TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
       TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
@@ -8307,6 +8521,12 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
          && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
                        TREE_TYPE (TREE_TYPE (old_decl))))
        {
+         if (stdarg_p (TREE_TYPE (old_decl)))
+           {
+             warning_at (loc, 0, "%q+D defined as variadic function "
+                         "without prototype", decl1);
+             locate_old_decl (old_decl);
+           }
          TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
                                              TREE_TYPE (decl1));
          current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
@@ -8545,8 +8765,11 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
            continue;
          /* If we got something other than a PARM_DECL it is an error.  */
          if (TREE_CODE (decl) != PARM_DECL)
-           error_at (DECL_SOURCE_LOCATION (decl),
-                     "%qD declared as a non-parameter", decl);
+           {
+             error_at (DECL_SOURCE_LOCATION (decl),
+                       "%qD declared as a non-parameter", decl);
+             continue;
+           }
          /* If the declaration is already marked, we have a duplicate
             name.  Complain and ignore the duplicate.  */
          else if (seen_args.contains (decl))
@@ -8915,7 +9138,8 @@ temp_pop_parm_decls (void)
   current_scope->bindings = NULL;
   for (; b; b = free_binding_and_advance (b))
     {
-      gcc_assert (TREE_CODE (b->decl) == PARM_DECL);
+      gcc_assert (TREE_CODE (b->decl) == PARM_DECL
+                 || b->decl == error_mark_node);
       gcc_assert (I_SYMBOL_BINDING (b->id) == b);
       I_SYMBOL_BINDING (b->id) = b->shadowed;
       if (b->shadowed && b->shadowed->u.type)
@@ -9028,6 +9252,10 @@ finish_function (void)
      function.  */
   maybe_warn_unused_local_typedefs ();
 
+  /* Possibly warn about unused parameters.  */
+  if (warn_unused_parameter)
+    do_warn_unused_parameter (fndecl);
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -9037,7 +9265,9 @@ finish_function (void)
 
   /* For GNU C extern inline functions disregard inline limits.  */
   if (DECL_EXTERNAL (fndecl)
-      && DECL_DECLARED_INLINE_P (fndecl))
+      && DECL_DECLARED_INLINE_P (fndecl)
+      && (flag_gnu89_inline
+         || lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (fndecl))))
     DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
 
   /* Genericize before inlining.  Delay genericizing nested functions
@@ -9401,38 +9631,12 @@ struct c_declspecs *
 build_null_declspecs (void)
 {
   struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
-  memset (&ret->locations, 0, cdw_number_of_elements);
-  ret->type = 0;
-  ret->expr = 0;
-  ret->decl_attr = 0;
-  ret->attrs = 0;
+  memset (ret, 0, sizeof *ret);
   ret->align_log = -1;
   ret->typespec_word = cts_none;
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
-  ret->declspecs_seen_p = false;
   ret->typespec_kind = ctsk_none;
-  ret->non_sc_seen_p = false;
-  ret->typedef_p = false;
-  ret->explicit_signed_p = false;
-  ret->deprecated_p = false;
-  ret->default_int_p = false;
-  ret->long_p = false;
-  ret->long_long_p = false;
-  ret->short_p = false;
-  ret->signed_p = false;
-  ret->unsigned_p = false;
-  ret->complex_p = false;
-  ret->inline_p = false;
-  ret->noreturn_p = false;
-  ret->thread_p = false;
-  ret->thread_gnu_p = false;
-  ret->const_p = false;
-  ret->volatile_p = false;
-  ret->atomic_p = false;
-  ret->restrict_p = false;
-  ret->saturating_p = false;
-  ret->alignas_p = false;
   ret->address_space = ADDR_SPACE_GENERIC;
   return ret;
 }
@@ -9474,32 +9678,48 @@ declspecs_add_qual (source_location loc,
   gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
              && C_IS_RESERVED_WORD (qual));
   i = C_RID_CODE (qual);
+  location_t prev_loc = 0;
   switch (i)
     {
     case RID_CONST:
       dupe = specs->const_p;
       specs->const_p = true;
+      prev_loc = specs->locations[cdw_const];
       specs->locations[cdw_const] = loc;
       break;
     case RID_VOLATILE:
       dupe = specs->volatile_p;
       specs->volatile_p = true;
+      prev_loc = specs->locations[cdw_volatile];
       specs->locations[cdw_volatile] = loc;
       break;
     case RID_RESTRICT:
       dupe = specs->restrict_p;
       specs->restrict_p = true;
+      prev_loc = specs->locations[cdw_restrict];
       specs->locations[cdw_restrict] = loc;
       break;
     case RID_ATOMIC:
       dupe = specs->atomic_p;
       specs->atomic_p = true;
+      prev_loc = specs->locations[cdw_atomic];
+      specs->locations[cdw_atomic] = loc;
       break;
     default:
       gcc_unreachable ();
     }
   if (dupe)
-    pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %qE", qual);
+    {
+      bool warned = pedwarn_c90 (loc, OPT_Wpedantic,
+                                "duplicate %qE declaration specifier", qual);
+      if (!warned
+         && warn_duplicate_decl_specifier
+         && prev_loc >= RESERVED_LOCATION_COUNT
+         && !from_macro_expansion_at (prev_loc)
+         && !from_macro_expansion_at (loc))
+       warning_at (loc, OPT_Wduplicate_decl_specifier,
+                   "duplicate %qE declaration specifier", qual);
+    }
   return specs;
 }
 
@@ -9584,6 +9804,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                error_at (loc,
                          ("both %<long%> and %<float%> in "
                           "declaration specifiers"));
+             else if (specs->typespec_word == cts_floatn_nx)
+               error_at (loc,
+                         ("both %<long%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
              else if (specs->typespec_word == cts_dfloat32)
                error_at (loc,
                          ("both %<long%> and %<_Decimal32%> in "
@@ -9637,6 +9865,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                error_at (loc,
                          ("both %<short%> and %<double%> in "
                           "declaration specifiers"));
+             else if (specs->typespec_word == cts_floatn_nx)
+               error_at (loc,
+                         ("both %<short%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
              else if (specs->typespec_word == cts_dfloat32)
                 error_at (loc,
                          ("both %<short%> and %<_Decimal32%> in "
@@ -9681,6 +9917,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                error_at (loc,
                          ("both %<signed%> and %<double%> in "
                           "declaration specifiers"));
+             else if (specs->typespec_word == cts_floatn_nx)
+               error_at (loc,
+                         ("both %<signed%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
              else if (specs->typespec_word == cts_dfloat32)
                error_at (loc,
                          ("both %<signed%> and %<_Decimal32%> in "
@@ -9725,6 +9969,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                error_at (loc,
                          ("both %<unsigned%> and %<double%> in "
                           "declaration specifiers"));
+             else if (specs->typespec_word == cts_floatn_nx)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
               else if (specs->typespec_word == cts_dfloat32)
                error_at (loc,
                          ("both %<unsigned%> and %<_Decimal32%> in "
@@ -9829,6 +10081,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                error_at (loc,
                          ("both %<_Sat%> and %<double%> in "
                           "declaration specifiers"));
+             else if (specs->typespec_word == cts_floatn_nx)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
               else if (specs->typespec_word == cts_dfloat32)
                error_at (loc,
                          ("both %<_Sat%> and %<_Decimal32%> in "
@@ -9862,8 +10122,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
        }
       else
        {
-         /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-            "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+         /* "void", "_Bool", "char", "int", "float", "double",
+            "_FloatN", "_FloatNx", "_Decimal32", "__intN",
+            "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
             "__auto_type".  */
          if (specs->typespec_word != cts_none)
            {
@@ -9929,10 +10190,13 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                          ("both %<__int%d%> and %<short%> in "
                           "declaration specifiers"),
                          int_n_data[specs->int_n_idx].bitsize);
-             else if (! int_n_enabled_p [specs->int_n_idx])
-               error_at (loc,
-                         "%<__int%d%> is not supported on this target",
-                         int_n_data[specs->int_n_idx].bitsize);
+             else if (! int_n_enabled_p[specs->int_n_idx])
+               {
+                 specs->typespec_word = cts_int_n;
+                 error_at (loc,
+                           "%<__int%d%> is not supported on this target",
+                           int_n_data[specs->int_n_idx].bitsize);
+               }
              else
                {
                  specs->typespec_word = cts_int_n;
@@ -10088,6 +10352,72 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
                  specs->locations[cdw_typespec] = loc;
                }
              return specs;
+           CASE_RID_FLOATN_NX:
+             specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
+             if (!in_system_header_at (input_location))
+               pedwarn (loc, OPT_Wpedantic,
+                        "ISO C does not support the %<_Float%d%s%> type",
+                        floatn_nx_types[specs->floatn_nx_idx].n,
+                        (floatn_nx_types[specs->floatn_nx_idx].extended
+                         ? "x"
+                         : ""));
+
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
+             else if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
+             else if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Float%d%s%> in "
+                          "declaration specifiers"),
+                         floatn_nx_types[specs->floatn_nx_idx].n,
+                         (floatn_nx_types[specs->floatn_nx_idx].extended
+                          ? "x"
+                          : ""));
+             else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+               {
+                 specs->typespec_word = cts_floatn_nx;
+                 error_at (loc,
+                           "%<_Float%d%s%> is not supported on this target",
+                           floatn_nx_types[specs->floatn_nx_idx].n,
+                           (floatn_nx_types[specs->floatn_nx_idx].extended
+                            ? "x"
+                            : ""));
+               }
+             else
+               {
+                 specs->typespec_word = cts_floatn_nx;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
            case RID_DFLOAT32:
            case RID_DFLOAT64:
            case RID_DFLOAT128:
@@ -10565,6 +10895,16 @@ finish_declspecs (struct c_declspecs *specs)
                         : double_type_node);
        }
       break;
+    case cts_floatn_nx:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p);
+      if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+       specs->type = integer_type_node;
+      else if (specs->complex_p)
+       specs->type = COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+      else
+       specs->type = FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+      break;
     case cts_dfloat32:
     case cts_dfloat64:
     case cts_dfloat128:
@@ -10688,11 +11028,22 @@ c_write_global_declarations_1 (tree globals)
       if (TREE_CODE (decl) == FUNCTION_DECL
          && DECL_INITIAL (decl) == 0
          && DECL_EXTERNAL (decl)
-         && !TREE_PUBLIC (decl)
-         && C_DECL_USED (decl))
+         && !TREE_PUBLIC (decl))
        {
-         pedwarn (input_location, 0, "%q+F used but never defined", decl);
-         TREE_NO_WARNING (decl) = 1;
+         if (C_DECL_USED (decl))
+           {
+             pedwarn (input_location, 0, "%q+F used but never defined", decl);
+             TREE_NO_WARNING (decl) = 1;
+           }
+         /* For -Wunused-function warn about unused static prototypes.  */
+         else if (warn_unused_function
+                  && ! DECL_ARTIFICIAL (decl)
+                  && ! TREE_NO_WARNING (decl))
+           {
+             warning (OPT_Wunused_function,
+                      "%q+F declared %<static%> but never defined", decl);
+             TREE_NO_WARNING (decl) = 1;
+           }
        }
 
       wrapup_global_declaration_1 (decl);