diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index a36397b..356518f 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1376,9 +1376,10 @@ static tree c_parser_attributes (c_parser *);
 static struct c_expr c_parser_initializer (c_parser *);
 static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
 					   struct obstack *);
-static void c_parser_initelt (c_parser *, struct obstack *);
-static void c_parser_initval (c_parser *, struct c_expr *,
-			      struct obstack *);
+static void c_parser_initelt (c_parser *, struct obstack *, bool *,
+                              HOST_WIDE_INT *, location_t *);
+static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *,
+			      bool *, HOST_WIDE_INT *, location_t *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
 static void c_parser_label (c_parser *);
@@ -4568,6 +4569,12 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   matching_braces braces;
   braces.consume_open (parser);
+  bool to_warn_excess_elements = false;
+  HOST_WIDE_INT warn_expected_elements = 0;
+  HOST_WIDE_INT warn_extra_elements = 0;
+  location_t warn_end_loc = 0;
+  location_t warn_start_loc = 0;
+  warn_start_loc = 0;
   if (nested_p)
     {
       finish_implicit_inits (brace_loc, outer_obstack);
@@ -4585,7 +4592,9 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
 	 comma.  */
       while (true)
 	{
-	  c_parser_initelt (parser, &braced_init_obstack);
+	  c_parser_initelt (parser, &braced_init_obstack,
+			    &to_warn_excess_elements, &warn_expected_elements,
+			    &warn_start_loc);
 	  if (parser->error)
 	    break;
 	  if (c_parser_next_token_is (parser, CPP_COMMA))
@@ -4597,8 +4606,25 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
 	    break;
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
 	    break;
+	  if (to_warn_excess_elements)
+	    {
+	      ++warn_extra_elements;
+	      warn_end_loc = c_parser_peek_token(parser)->location;
+	    }
 	}
     }
+  if (to_warn_excess_elements && !(parser->error))
+    {
+      if (! warn_end_loc)
+	warn_end_loc = warn_start_loc;
+      location_t combined_loc = make_location (warn_start_loc, warn_start_loc,
+					       warn_end_loc);
+      pedwarn_init (combined_loc, 0,
+		    "excess elements in array initializer "
+		    "(%wu elements, %wu expected)",
+		    warn_expected_elements + warn_extra_elements + 1,
+		    warn_expected_elements);
+    }
   c_token *next_tok = c_parser_peek_token (parser);
   if (next_tok->type != CPP_CLOSE_BRACE)
     {
@@ -4621,7 +4647,9 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
 /* Parse a nested initializer, including designators.  */
 
 static void
-c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack,
+                  bool *to_warn_excess_elements,
+                  HOST_WIDE_INT *warn_expected_elements, location_t *warn_start_loc)
 {
   /* Parse any designator or designator list.  A single array
      designator may have the subsequent "=" omitted in GNU C, but a
@@ -4757,7 +4785,9 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 		  /* Now parse and process the remainder of the
 		     initializer, starting with this message
 		     expression as a primary-expression.  */
-		  c_parser_initval (parser, &mexpr, braced_init_obstack);
+		  c_parser_initval (parser, &mexpr, braced_init_obstack,
+				    to_warn_excess_elements, warn_expected_elements,
+				    warn_start_loc);
 		  return;
 		}
 	      c_parser_consume_token (parser);
@@ -4817,7 +4847,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 	    }
 	}
     }
-  c_parser_initval (parser, NULL, braced_init_obstack);
+  c_parser_initval (parser, NULL, braced_init_obstack, to_warn_excess_elements,
+		    warn_expected_elements, warn_start_loc);
 }
 
 /* Parse a nested initializer; as c_parser_initializer but parses
@@ -4828,7 +4859,10 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 
 static void
 c_parser_initval (c_parser *parser, struct c_expr *after,
-		  struct obstack * braced_init_obstack)
+		  struct obstack * braced_init_obstack,
+		  bool *to_warn_excess_elements,
+		  HOST_WIDE_INT *warn_expected_elements,
+		  location_t *warn_start_loc)
 {
   struct c_expr init;
   gcc_assert (!after || c_dialect_objc ());
@@ -4845,7 +4879,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
 	  && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
 	init = convert_lvalue_to_rvalue (loc, init, true, true);
     }
-  process_init_element (loc, init, false, braced_init_obstack);
+  process_init_element (loc, init, false, braced_init_obstack,
+			to_warn_excess_elements, warn_expected_elements,
+			warn_start_loc);
 }
 
 /* Parse a compound statement (possibly a function body) (C90 6.6.2,
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 96c7ae7..7fb804c 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -662,13 +662,21 @@ extern void start_init (tree, tree, int, rich_location *);
 extern void finish_init (void);
 extern void really_start_incremental_init (tree);
 extern void finish_implicit_inits (location_t, struct obstack *);
-extern void push_init_level (location_t, int, struct obstack *);
+extern void push_init_level (location_t, int, struct obstack *,
+			     bool *to_warn_excess_elements = NULL,
+			     HOST_WIDE_INT *warn_expected_elements = 0,
+			     location_t *warn_start_loc = 0);
 extern struct c_expr pop_init_level (location_t, int, struct obstack *,
 				     location_t);
 extern void set_init_index (location_t, tree, tree, struct obstack *);
 extern void set_init_label (location_t, tree, location_t, struct obstack *);
 extern void process_init_element (location_t, struct c_expr, bool,
-				  struct obstack *);
+				  struct obstack *,
+				  bool *to_warn_excess_elements = NULL,
+				  HOST_WIDE_INT *warn_expected_elements = 0,
+				  location_t *warn_start_loc = 0);
+extern void pedwarn_init (location_t, int, const char *, ...)
+    ATTRIBUTE_GCC_DIAG (3,0);
 extern tree build_compound_literal (location_t, tree, tree, bool);
 extern void check_compound_literal_type (location_t, struct c_type_name *);
 extern tree c_start_case (location_t, location_t, tree, bool);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 73e7460..0f42570 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6124,7 +6124,7 @@ error_init (location_t loc, const char *gmsgid)
    it is unconditionally given.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
-static void ATTRIBUTE_GCC_DIAG (3,0)
+void ATTRIBUTE_GCC_DIAG (3,0)
 pedwarn_init (location_t loc, int opt, const char *gmsgid, ...)
 {
   /* Use the location where a macro was expanded rather than where
@@ -7961,7 +7961,10 @@ finish_implicit_inits (location_t loc, struct obstack *braced_init_obstack)
 
 void
 push_init_level (location_t loc, int implicit,
-		 struct obstack *braced_init_obstack)
+		 struct obstack *braced_init_obstack,
+		 bool *to_warn_excess_elements,
+		 HOST_WIDE_INT *warn_expected_elements,
+		 location_t *warn_start_loc)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -7973,7 +7976,19 @@ push_init_level (location_t loc, int implicit,
       if (RECORD_OR_UNION_TYPE_P (constructor_type) && constructor_fields)
 	value = find_init_member (constructor_fields, braced_init_obstack);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-	value = find_init_member (constructor_index, braced_init_obstack);
+	{
+	  if (constructor_max_index != NULL_TREE
+	      && constructor_index != NULL_TREE
+	      && tree_int_cst_lt (constructor_max_index, constructor_index))
+	    {
+	      if (to_warn_excess_elements && *to_warn_excess_elements == false)
+		{
+		  *to_warn_excess_elements = true;
+		  *warn_start_loc = loc;
+		}
+	    }
+	  value = find_init_member (constructor_index, braced_init_obstack);
+	}
     }
 
   p = XNEW (struct constructor_stack);
@@ -8135,6 +8150,17 @@ push_init_level (location_t loc, int implicit,
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
+
+  if (to_warn_excess_elements && *to_warn_excess_elements == false
+      && constructor_type != error_mark_node
+      && TREE_CODE (constructor_type) == ARRAY_TYPE
+      && constructor_max_index != NULL_TREE)
+    {
+      tree subtype = TYPE_MAIN_VARIANT(TREE_TYPE (constructor_type));
+      if (TREE_CODE (subtype) != ARRAY_TYPE
+	  && tree_fits_uhwi_p (constructor_max_index))
+	*warn_expected_elements += (tree_to_uhwi(constructor_max_index) + 1);
+    }
 }
 
 /* At the end of an implicit or explicit brace level,
@@ -9389,7 +9415,10 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
 
 void
 process_init_element (location_t loc, struct c_expr value, bool implicit,
-		      struct obstack * braced_init_obstack)
+		      struct obstack * braced_init_obstack,
+		      bool *to_warn_excess_elements,
+		      HOST_WIDE_INT *warn_expected_elements,
+		      location_t *warn_start_loc)
 {
   tree orig_value = value.value;
   int string_flag
@@ -9552,7 +9581,10 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
 		   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
 		       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
 	    {
-	      push_init_level (loc, 1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack,
+			       to_warn_excess_elements, warn_expected_elements,
+			       warn_start_loc);
+
 	      continue;
 	    }
 
@@ -9644,7 +9676,10 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
 		   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
 		       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
 	    {
-	      push_init_level (loc, 1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack,
+			       to_warn_excess_elements,
+			       warn_expected_elements, warn_start_loc);
+
 	      continue;
 	    }
 
@@ -9686,7 +9721,9 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
 		   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
 		       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
 	    {
-	      push_init_level (loc, 1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack,
+			       to_warn_excess_elements,
+			       warn_expected_elements, warn_start_loc);
 	      continue;
 	    }
 
@@ -9694,8 +9731,16 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
 	      && (tree_int_cst_lt (constructor_max_index, constructor_index)
 		  || integer_all_onesp (constructor_max_index)))
 	    {
-	      pedwarn_init (loc, 0,
-			    "excess elements in array initializer");
+	      if (to_warn_excess_elements && *to_warn_excess_elements == false)
+		{
+		  *to_warn_excess_elements = true;
+		  if (tree_fits_uhwi_p (constructor_max_index))
+		    {
+		      *warn_expected_elements += \
+			(tree_to_uhwi (constructor_max_index) + 1);
+		    }
+		  *warn_start_loc = loc;
+		}
 	      break;
 	    }
 
