Patchwork [C] Add location to error_init (PR c/61096)

login
register
mail settings
Submitter Marek Polacek
Date May 9, 2014, 7:27 a.m.
Message ID <20140509072727.GF11802@redhat.com>
Download mbox | patch
Permalink /patch/347307/
State New
Headers show

Comments

Marek Polacek - May 9, 2014, 7:27 a.m.
Another piece of puzzle.  error_init didn't have a location parameter,
so initialization errors had wrong column info.  This patch adds
location parameter to error_init and to a few of other functions.
The testcases show what has better column info now.
Note what I wrote in
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61096#c3 -- three
error_init calls seem to be unreachable, bonus points for anyone who
can construct a testcase that triggers them ;).  And neither testsuite nor
bootstrap exercises them I think.
Many pedwarn_init calls still use input_location; I'm going to address
that later when I find some time.

Regtested/bootstrapped on x86_64-linux, ok for trunk?

2014-05-09  Marek Polacek  <polacek@redhat.com>

	PR c/61096
	* c-parser.c (c_parser_braced_init): Pass brace_loc to push_init_level.
	(c_parser_initelt): Pass location to set_init_label.  Pass array index
	location to set_init_index.
	* c-tree.h (push_init_level): Update declaration.
	(pop_init_level): Likewise.
	(set_init_index): Likewise.
	(set_init_label): Likewise.
	* c-typeck.c (error_init): Add location parameter.  Call error_at
	instead of error.
	(digest_init): Pass init_loc to error_init.
	(really_start_incremental_init):
	(push_init_level): Add location parameter.  Pass loc to pop_init_level
	and error_init.
	(pop_init_level): Likewise.
	(set_designator): Add location parameter.  Pass loc to pop_init_level,
	push_init_level, and error_init.
	(set_init_index): Add location parameter.  Pass loc to error_init and
	set_designator.
	(set_init_label): Likewise.
	(output_init_element): Pass loc to error_init.
	(process_init_element): Pass loc to error_init, pop_init_level,
	pedwarn_init, and push_init_level.

	* gcc.dg/pr61096-1.c: New test.
	* gcc.dg/pr61096-2.c: New test.


	Marek
Joseph S. Myers - May 9, 2014, 4:53 p.m.
On Fri, 9 May 2014, Marek Polacek wrote:

> Another piece of puzzle.  error_init didn't have a location parameter,
> so initialization errors had wrong column info.  This patch adds
> location parameter to error_init and to a few of other functions.
> The testcases show what has better column info now.
> Note what I wrote in
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61096#c3 -- three
> error_init calls seem to be unreachable, bonus points for anyone who
> can construct a testcase that triggers them ;).  And neither testsuite nor
> bootstrap exercises them I think.
> Many pedwarn_init calls still use input_location; I'm going to address
> that later when I find some time.
> 
> Regtested/bootstrapped on x86_64-linux, ok for trunk?

OK.
Jeff Law - May 9, 2014, 8:32 p.m.
On 05/09/14 01:27, Marek Polacek wrote:
> Another piece of puzzle.  error_init didn't have a location parameter,
> so initialization errors had wrong column info.  This patch adds
> location parameter to error_init and to a few of other functions.
> The testcases show what has better column info now.
> Note what I wrote in
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=61096#c3 -- three
> error_init calls seem to be unreachable, bonus points for anyone who
> can construct a testcase that triggers them ;).  And neither testsuite nor
> bootstrap exercises them I think.
> Many pedwarn_init calls still use input_location; I'm going to address
> that later when I find some time.
>
> Regtested/bootstrapped on x86_64-linux, ok for trunk?
>
> 2014-05-09  Marek Polacek  <polacek@redhat.com>
>
> 	PR c/61096
> 	* c-parser.c (c_parser_braced_init): Pass brace_loc to push_init_level.
> 	(c_parser_initelt): Pass location to set_init_label.  Pass array index
> 	location to set_init_index.
> 	* c-tree.h (push_init_level): Update declaration.
> 	(pop_init_level): Likewise.
> 	(set_init_index): Likewise.
> 	(set_init_label): Likewise.
> 	* c-typeck.c (error_init): Add location parameter.  Call error_at
> 	instead of error.
> 	(digest_init): Pass init_loc to error_init.
> 	(really_start_incremental_init):
> 	(push_init_level): Add location parameter.  Pass loc to pop_init_level
> 	and error_init.
> 	(pop_init_level): Likewise.
> 	(set_designator): Add location parameter.  Pass loc to pop_init_level,
> 	push_init_level, and error_init.
> 	(set_init_index): Add location parameter.  Pass loc to error_init and
> 	set_designator.
> 	(set_init_label): Likewise.
> 	(output_init_element): Pass loc to error_init.
> 	(process_init_element): Pass loc to error_init, pop_init_level,
> 	pedwarn_init, and push_init_level.
>
> 	* gcc.dg/pr61096-1.c: New test.
> 	* gcc.dg/pr61096-2.c: New test.
OK.
Jeff

Patch

diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index 6e8f33b..459240f 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -4138,7 +4138,7 @@  c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
   gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
   c_parser_consume_token (parser);
   if (nested_p)
-    push_init_level (0, &braced_init_obstack);
+    push_init_level (brace_loc, 0, &braced_init_obstack);
   else
     really_start_incremental_init (type);
   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -4168,12 +4168,12 @@  c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
-      pop_init_level (0, &braced_init_obstack);
+      pop_init_level (brace_loc, 0, &braced_init_obstack);
       obstack_free (&braced_init_obstack, NULL);
       return ret;
     }
   c_parser_consume_token (parser);
-  ret = pop_init_level (0, &braced_init_obstack);
+  ret = pop_init_level (brace_loc, 0, &braced_init_obstack);
   obstack_free (&braced_init_obstack, NULL);
   return ret;
 }
@@ -4190,7 +4190,8 @@  c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
       && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
     {
       /* Old-style structure member designator.  */
-      set_init_label (c_parser_peek_token (parser)->value,
+      set_init_label (c_parser_peek_token (parser)->location,
+		      c_parser_peek_token (parser)->value,
 		      braced_init_obstack);
       /* Use the colon as the error location.  */
       pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
@@ -4219,7 +4220,7 @@  c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 	      c_parser_consume_token (parser);
 	      if (c_parser_next_token_is (parser, CPP_NAME))
 		{
-		  set_init_label (c_parser_peek_token (parser)->value,
+		  set_init_label (des_loc, c_parser_peek_token (parser)->value,
 				  braced_init_obstack);
 		  c_parser_consume_token (parser);
 		}
@@ -4240,6 +4241,7 @@  c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 	    {
 	      tree first, second;
 	      location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+	      location_t array_index_loc = UNKNOWN_LOCATION;
 	      /* ??? Following the old parser, [ objc-receiver
 		 objc-message-args ] is accepted as an initializer,
 		 being distinguished from a designator by what follows
@@ -4317,6 +4319,7 @@  c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 		  return;
 		}
 	      c_parser_consume_token (parser);
+	      array_index_loc = c_parser_peek_token (parser)->location;
 	      first = c_parser_expr_no_commas (parser, NULL).value;
 	      mark_exp_read (first);
 	    array_desig_after_first:
@@ -4332,7 +4335,8 @@  c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
 	      if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
 		{
 		  c_parser_consume_token (parser);
-		  set_init_index (first, second, braced_init_obstack);
+		  set_init_index (array_index_loc, first, second,
+				  braced_init_obstack);
 		  if (second)
 		    pedwarn (ellipsis_loc, OPT_Wpedantic,
 			     "ISO C forbids specifying range of elements to initialize");
diff --git gcc/c/c-tree.h gcc/c/c-tree.h
index a6e7327..ae932fa 100644
--- gcc/c/c-tree.h
+++ gcc/c/c-tree.h
@@ -606,10 +606,10 @@  extern void maybe_warn_string_init (tree, struct c_expr);
 extern void start_init (tree, tree, int);
 extern void finish_init (void);
 extern void really_start_incremental_init (tree);
-extern void push_init_level (int, struct obstack *);
-extern struct c_expr pop_init_level (int, struct obstack *);
-extern void set_init_index (tree, tree, struct obstack *);
-extern void set_init_label (tree, struct obstack *);
+extern void push_init_level (location_t, int, struct obstack *);
+extern struct c_expr pop_init_level (location_t, int, struct obstack *);
+extern void set_init_index (location_t, tree, tree, struct obstack *);
+extern void set_init_label (location_t, tree, struct obstack *);
 extern void process_init_element (location_t, struct c_expr, bool,
 				  struct obstack *);
 extern tree build_compound_literal (location_t, tree, tree, bool);
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 7d2df6b..6798801 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -106,7 +106,7 @@  static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
 static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
 				 bool, struct obstack *);
 static void output_pending_init_elements (int, struct obstack *);
-static int set_designator (int, struct obstack *);
+static int set_designator (location_t, int, struct obstack *);
 static void push_range_stack (tree, struct obstack *);
 static void add_pending_init (location_t, tree, tree, tree, bool,
 			      struct obstack *);
@@ -5545,15 +5545,15 @@  convert_to_anonymous_field (location_t location, tree type, tree rhs)
    The component name is taken from the spelling stack.  */
 
 static void
-error_init (const char *gmsgid)
+error_init (location_t loc, const char *gmsgid)
 {
   char *ofwhat;
 
   /* The gmsgid may be a format string with %< and %>. */
-  error (gmsgid);
+  error_at (loc, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    error ("(near initialization for %qs)", ofwhat);
+    error_at (loc, "(near initialization for %qs)", ofwhat);
 }
 
 /* Issue a pedantic warning for a bad initializer component.  OPT is
@@ -6555,7 +6555,8 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	    {
 	      if (typ2 != char_type_node)
 		{
-		  error_init ("char-array initialized from wide string");
+		  error_init (init_loc, "char-array initialized from wide "
+			      "string");
 		  return error_mark_node;
 		}
 	    }
@@ -6563,14 +6564,14 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	    {
 	      if (typ2 == char_type_node)
 		{
-		  error_init ("wide character array initialized from non-wide "
-			      "string");
+		  error_init (init_loc, "wide character array initialized "
+			      "from non-wide string");
 		  return error_mark_node;
 		}
 	      else if (!comptypes(typ1, typ2))
 		{
-		  error_init ("wide character array initialized from "
-			      "incompatible wide string");
+		  error_init (init_loc, "wide character array initialized "
+			      "from incompatible wide string");
 		  return error_mark_node;
 		}
 	    }
@@ -6603,7 +6604,7 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	}
       else if (INTEGRAL_TYPE_P (typ1))
 	{
-	  error_init ("array of inappropriate type initialized "
+	  error_init (init_loc, "array of inappropriate type initialized "
 		      "from string constant");
 	  return error_mark_node;
 	}
@@ -6671,7 +6672,7 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 		  (init_loc, inside_init);
 	      else
 		{
-		  error_init ("invalid use of non-lvalue array");
+		  error_init (init_loc, "invalid use of non-lvalue array");
 		  return error_mark_node;
 		}
 	    }
@@ -6697,7 +6698,8 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
       if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
 	  && TREE_CODE (inside_init) != CONSTRUCTOR)
 	{
-	  error_init ("array initialized from non-constant array expression");
+	  error_init (init_loc, "array initialized from non-constant array "
+		      "expression");
 	  return error_mark_node;
 	}
 
@@ -6711,7 +6713,7 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	    = valid_compound_expr_initializer (inside_init,
 					       TREE_TYPE (inside_init));
 	  if (inside_init == error_mark_node)
-	    error_init ("initializer element is not constant");
+	    error_init (init_loc, "initializer element is not constant");
 	  else
 	    pedwarn_init (init_loc, OPT_Wpedantic,
 			  "initializer element is not constant");
@@ -6722,7 +6724,7 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	       && !initializer_constant_valid_p (inside_init,
 						 TREE_TYPE (inside_init)))
 	{
-	  error_init ("initializer element is not constant");
+	  error_init (init_loc, "initializer element is not constant");
 	  inside_init = error_mark_node;
 	}
       else if (require_constant && !maybe_const)
@@ -6762,14 +6764,15 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	;
       else if (require_constant && !TREE_CONSTANT (inside_init))
 	{
-	  error_init ("initializer element is not constant");
+	  error_init (init_loc, "initializer element is not constant");
 	  inside_init = error_mark_node;
 	}
       else if (require_constant
 	       && !initializer_constant_valid_p (inside_init,
 						 TREE_TYPE (inside_init)))
 	{
-	  error_init ("initializer element is not computable at load time");
+	  error_init (init_loc, "initializer element is not computable at "
+		      "load time");
 	  inside_init = error_mark_node;
 	}
       else if (require_constant && !maybe_const)
@@ -6783,11 +6786,11 @@  digest_init (location_t init_loc, tree type, tree init, tree origtype,
 
   if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
     {
-      error_init ("variable-sized object may not be initialized");
+      error_init (init_loc, "variable-sized object may not be initialized");
       return error_mark_node;
     }
 
-  error_init ("invalid initializer");
+  error_init (init_loc, "invalid initializer");
   return error_mark_node;
 }
 
@@ -7165,7 +7168,8 @@  really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
-push_init_level (int implicit, struct obstack * braced_init_obstack)
+push_init_level (location_t loc, int implicit,
+		 struct obstack *braced_init_obstack)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -7184,14 +7188,14 @@  push_init_level (int implicit, struct obstack * braced_init_obstack)
 	       || TREE_CODE (constructor_type) == UNION_TYPE)
 	      && constructor_fields == 0)
 	    process_init_element (input_location,
-				  pop_init_level (1, braced_init_obstack),
+				  pop_init_level (loc, 1, braced_init_obstack),
 				  true, braced_init_obstack);
 	  else if (TREE_CODE (constructor_type) == ARRAY_TYPE
 		   && constructor_max_index
 		   && tree_int_cst_lt (constructor_max_index,
 				       constructor_index))
 	    process_init_element (input_location,
-				  pop_init_level (1, braced_init_obstack),
+				  pop_init_level (loc, 1, braced_init_obstack),
 				  true, braced_init_obstack);
 	  else
 	    break;
@@ -7281,7 +7285,7 @@  push_init_level (int implicit, struct obstack * braced_init_obstack)
 
   if (constructor_type == 0)
     {
-      error_init ("extra brace group at end of initializer");
+      error_init (loc, "extra brace group at end of initializer");
       constructor_fields = 0;
       constructor_unfilled_fields = 0;
       return;
@@ -7382,7 +7386,8 @@  push_init_level (int implicit, struct obstack * braced_init_obstack)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
-pop_init_level (int implicit, struct obstack * braced_init_obstack)
+pop_init_level (location_t loc, int implicit,
+		struct obstack *braced_init_obstack)
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -7396,7 +7401,7 @@  pop_init_level (int implicit, struct obstack * braced_init_obstack)
 	 pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
 	process_init_element (input_location,
-			      pop_init_level (1, braced_init_obstack),
+			      pop_init_level (loc, 1, braced_init_obstack),
 			      true, braced_init_obstack);
       gcc_assert (!constructor_range_stack);
     }
@@ -7423,7 +7428,7 @@  pop_init_level (int implicit, struct obstack * braced_init_obstack)
 	  gcc_assert (!TYPE_SIZE (constructor_type));
 
 	  if (constructor_depth > 2)
-	    error_init ("initialization of flexible array member in a nested context");
+	    error_init (loc, "initialization of flexible array member in a nested context");
 	  else
 	    pedwarn_init (input_location, OPT_Wpedantic,
 			  "initialization of a flexible array member");
@@ -7485,12 +7490,12 @@  pop_init_level (int implicit, struct obstack * braced_init_obstack)
       if (vec_safe_is_empty (constructor_elements))
 	{
 	  if (!constructor_erroneous)
-	    error_init ("empty scalar initializer");
+	    error_init (loc, "empty scalar initializer");
 	  ret.value = error_mark_node;
 	}
       else if (vec_safe_length (constructor_elements) != 1)
 	{
-	  error_init ("extra elements in scalar initializer");
+	  error_init (loc, "extra elements in scalar initializer");
 	  ret.value = (*constructor_elements)[0].value;
 	}
       else
@@ -7553,7 +7558,8 @@  pop_init_level (int implicit, struct obstack * braced_init_obstack)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
-set_designator (int array, struct obstack * braced_init_obstack)
+set_designator (location_t loc, int array,
+		struct obstack *braced_init_obstack)
 {
   tree subtype;
   enum tree_code subcode;
@@ -7576,7 +7582,7 @@  set_designator (int array, struct obstack * braced_init_obstack)
 	 braces.  */
       while (constructor_stack->implicit)
 	process_init_element (input_location,
-			      pop_init_level (1, braced_init_obstack),
+			      pop_init_level (loc, 1, braced_init_obstack),
 			      true, braced_init_obstack);
       constructor_designated = 1;
       return 0;
@@ -7600,17 +7606,17 @@  set_designator (int array, struct obstack * braced_init_obstack)
   subcode = TREE_CODE (subtype);
   if (array && subcode != ARRAY_TYPE)
     {
-      error_init ("array index in non-array initializer");
+      error_init (loc, "array index in non-array initializer");
       return 1;
     }
   else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
     {
-      error_init ("field name not in record or union initializer");
+      error_init (loc, "field name not in record or union initializer");
       return 1;
     }
 
   constructor_designated = 1;
-  push_init_level (2, braced_init_obstack);
+  push_init_level (loc, 2, braced_init_obstack);
   return 0;
 }
 
@@ -7643,10 +7649,10 @@  push_range_stack (tree range_end, struct obstack * braced_init_obstack)
    of indices, running from FIRST through LAST.  */
 
 void
-set_init_index (tree first, tree last,
+set_init_index (location_t loc, tree first, tree last,
 		struct obstack * braced_init_obstack)
 {
-  if (set_designator (1, braced_init_obstack))
+  if (set_designator (loc, 1, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -7654,7 +7660,7 @@  set_init_index (tree first, tree last,
   if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
       || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
     {
-      error_init ("array index in initializer not of integer type");
+      error_init (loc, "array index in initializer not of integer type");
       return;
     }
 
@@ -7677,16 +7683,16 @@  set_init_index (tree first, tree last,
     }
 
   if (TREE_CODE (first) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
+    error_init (loc, "nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
+    error_init (loc, "nonconstant array index in initializer");
   else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
-    error_init ("array index in non-array initializer");
+    error_init (loc, "array index in non-array initializer");
   else if (tree_int_cst_sgn (first) == -1)
-    error_init ("array index in initializer exceeds array bounds");
+    error_init (loc, "array index in initializer exceeds array bounds");
   else if (constructor_max_index
 	   && tree_int_cst_lt (constructor_max_index, first))
-    error_init ("array index in initializer exceeds array bounds");
+    error_init (loc, "array index in initializer exceeds array bounds");
   else
     {
       constant_expression_warning (first);
@@ -7705,7 +7711,7 @@  set_init_index (tree first, tree last,
 	    last = 0;
 	  else if (tree_int_cst_lt (last, first))
 	    {
-	      error_init ("empty index range in initializer");
+	      error_init (loc, "empty index range in initializer");
 	      last = 0;
 	    }
 	  else
@@ -7714,7 +7720,8 @@  set_init_index (tree first, tree last,
 	      if (constructor_max_index != 0
 		  && tree_int_cst_lt (constructor_max_index, last))
 		{
-		  error_init ("array index range in initializer exceeds array bounds");
+		  error_init (loc, "array index range in initializer exceeds "
+			      "array bounds");
 		  last = 0;
 		}
 	    }
@@ -7730,11 +7737,12 @@  set_init_index (tree first, tree last,
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
-set_init_label (tree fieldname, struct obstack * braced_init_obstack)
+set_init_label (location_t loc, tree fieldname,
+		struct obstack *braced_init_obstack)
 {
   tree field;
 
-  if (set_designator (0, braced_init_obstack))
+  if (set_designator (loc, 0, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -7742,7 +7750,7 @@  set_init_label (tree fieldname, struct obstack * braced_init_obstack)
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != UNION_TYPE)
     {
-      error_init ("field name not in record or union initializer");
+      error_init (loc, "field name not in record or union initializer");
       return;
     }
 
@@ -7761,7 +7769,7 @@  set_init_label (tree fieldname, struct obstack * braced_init_obstack)
 	field = TREE_CHAIN (field);
 	if (field)
 	  {
-	    if (set_designator (0, braced_init_obstack))
+	    if (set_designator (loc, 0, braced_init_obstack))
 	      return;
 	  }
       }
@@ -8261,7 +8269,7 @@  output_init_element (location_t loc, tree value, tree origtype,
     {
       if (require_constant_value)
 	{
-	  error_init ("initializer element is not constant");
+	  error_init (loc, "initializer element is not constant");
 	  value = error_mark_node;
 	}
       else if (require_constant_elements)
@@ -8582,14 +8590,14 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
-	error_init ("excess elements in char array initializer");
+	error_init (loc, "excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
 
   if (constructor_stack->replacement_value.value != 0)
     {
-      error_init ("excess elements in struct initializer");
+      error_init (loc, "excess elements in struct initializer");
       return;
     }
 
@@ -8605,14 +8613,16 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
 	   || TREE_CODE (constructor_type) == UNION_TYPE)
 	  && constructor_fields == 0)
-	process_init_element (loc, pop_init_level (1, braced_init_obstack),
+	process_init_element (loc,
+			      pop_init_level (loc, 1, braced_init_obstack),
 			      true, braced_init_obstack);
       else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
 	        || TREE_CODE (constructor_type) == VECTOR_TYPE)
 	       && constructor_max_index
 	       && tree_int_cst_lt (constructor_max_index,
 				   constructor_index))
-	process_init_element (loc, pop_init_level (1, braced_init_obstack),
+	process_init_element (loc,
+			      pop_init_level (loc, 1, braced_init_obstack),
 			      true, braced_init_obstack);
       else
 	break;
@@ -8649,8 +8659,7 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
 
 	  if (constructor_fields == 0)
 	    {
-	      pedwarn_init (input_location, 0,
-			    "excess elements in struct initializer");
+	      pedwarn_init (loc, 0, "excess elements in struct initializer");
 	      break;
 	    }
 
@@ -8665,7 +8674,8 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
 	      && TYPE_SIZE (fieldtype) == NULL_TREE
 	      && DECL_CHAIN (constructor_fields) == NULL_TREE)
 	    {
-	      error_init ("non-static initialization of a flexible array member");
+	      error_init (loc, "non-static initialization of a flexible "
+			  "array member");
 	      break;
 	    }
 
@@ -8683,7 +8693,7 @@  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 (1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack);
 	      continue;
 	    }
 
@@ -8775,7 +8785,7 @@  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 (1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack);
 	      continue;
 	    }
 
@@ -8817,7 +8827,7 @@  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 (1, braced_init_obstack);
+	      push_init_level (loc, 1, braced_init_obstack);
 	      continue;
 	    }
 
@@ -8918,7 +8928,8 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
 	    {
 	      gcc_assert (constructor_stack->implicit);
 	      process_init_element (loc,
-				    pop_init_level (1, braced_init_obstack),
+				    pop_init_level (loc, 1,
+						    braced_init_obstack),
 				    true, braced_init_obstack);
 	    }
 	  for (p = range_stack;
@@ -8927,7 +8938,8 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
 	    {
 	      gcc_assert (constructor_stack->implicit);
 	      process_init_element (loc,
-				    pop_init_level (1, braced_init_obstack),
+				    pop_init_level (loc, 1,
+						    braced_init_obstack),
 				    true, braced_init_obstack);
 	    }
 
@@ -8948,7 +8960,7 @@  process_init_element (location_t loc, struct c_expr value, bool implicit,
 	      p = p->next;
 	      if (!p)
 		break;
-	      push_init_level (2, braced_init_obstack);
+	      push_init_level (loc, 2, braced_init_obstack);
 	      p->stack = constructor_stack;
 	      if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
 		p->index = p->range_start;
diff --git gcc/testsuite/gcc.dg/pr61096-1.c gcc/testsuite/gcc.dg/pr61096-1.c
index e69de29..3f7d60c 100644
--- gcc/testsuite/gcc.dg/pr61096-1.c
+++ gcc/testsuite/gcc.dg/pr61096-1.c
@@ -0,0 +1,61 @@ 
+/* PR c/61077 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -fshort-enums -fshort-wchar -Wpedantic" } */
+/* { dg-prune-output ".*near initialization for.*" } */
+
+typedef enum { A } schar;
+extern int e;
+struct S
+{
+  int a[3];
+};
+struct f
+{
+  int w;
+  int x[];
+};
+struct g
+{
+  struct f f; /* { dg-warning "invalid use of structure with flexible array member" } */
+};
+
+char w1[] = L"foo"; /* { dg-error "13:char-array initialized from wide string" } */
+__WCHAR_TYPE__ w2[] = "foo"; /* { dg-error "23:wide character array initialized from non-wide string" } */
+__WCHAR_TYPE__ w3[] = U"foo"; /* { dg-error "23:wide character array initialized from incompatible wide string" } */
+schar a1[] = "foo"; /* { dg-error "14:array of inappropriate type initialized from string constant" } */
+int a2[] = (int[]) { 1 }; /* { dg-error "12:array initialized from non-constant array expression" } */
+
+int a3 = e; /* { dg-error "10:initializer element is not constant" } */
+int a4 = (e, 1); /* { dg-error "10:initializer element is not constant" } */
+int a5 = a1[0]; /* { dg-error "10:initializer element is not constant" } */
+int a6 = &a3 - &a4; /* { dg-error "10:initializer element is not" } */
+int a7[] = a7; /* { dg-error "12:invalid initializer" } */
+
+struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of initializer" } */
+/* { dg-warning "23:excess elements in struct initializer" "" { target *-*-* } 34 } */
+struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */
+struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */
+
+__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */
+int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */
+int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */
+__extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */
+int a12 = {[1] = 2 }; /* { dg-error "13:array index in non-array initializer" } */
+int a13[2] = {[-1] = 4 }; /* { dg-error "16:array index in initializer exceeds array bounds" } */
+int a14[2] = {[64] = 4 }; /* { dg-error "16:array index in initializer exceeds array bounds" } */
+__extension__ int a15[10] = {[2 ... 1] = 4 }; /* { dg-error "31:empty index range in initializer" } */
+__extension__ int a16[10] = {[2 ... 100] = 4 }; /* { dg-error "31:array index range in initializer exceeds array bounds" } */
+int a17[] = { .B = 1 }; /* { dg-error "15:field name not in record or union initializer" } */
+int a18[] = { e }; /* { dg-error "15:initializer element is not constant" } */
+char a19[1] = { "x", "x" }; /* { dg-error "22:excess elements in char array initializer" } */
+
+void
+bar (void)
+{
+  struct f f = { 2, "c" }; /* { dg-error "21:non-static initialization of a flexible array member" } */
+}
+
+struct
+{
+  char *v;
+} sx[] = { .v = 0 }; /* { dg-error "12:field name not in record or union initializer" } */
diff --git gcc/testsuite/gcc.dg/pr61096-2.c gcc/testsuite/gcc.dg/pr61096-2.c
index e69de29..fbea4d9 100644
--- gcc/testsuite/gcc.dg/pr61096-2.c
+++ gcc/testsuite/gcc.dg/pr61096-2.c
@@ -0,0 +1,10 @@ 
+/* PR c/61077 */
+/* { dg-do compile } */
+
+struct s { char c[1]; };
+extern struct s foo (void);
+void
+bar (void)
+{
+  char *t = (foo ()).c; /* { dg-error "13:invalid use of non-lvalue array" } */
+}