The attached patch slightly changes the order in which initializers
are checked for type compatibility to issue the same error for static
initializers of incompatible types as for automatic objects, rather
than rejecting the former for their lack of constness first.

I originally closed the bug as WontFix but a better test case sent
by the submitter to gcc-help in a subsequent discussion convinced
me that there is an improvement to be made here:

  https://gcc.gnu.org/ml/gcc-help/2016-06/msg00057.html

Martin
PR c/71552 - Confusing error for incorrect struct initialization

gcc/c/ChangeLog:
2016-06-18  Martin Sebor  <mse...@redhat.com>

	PR c/71552
	* c-typeck.c (output_init_element): Diagnose incompatible types
	before non-constant initializers.

gcc/testsuite/ChangeLog:
2016-06-18  Martin Sebor  <mse...@redhat.com>

	PR c/71552
	* gcc.dg/init-bad-9.c: New test.

Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c	(revision 237461)
+++ gcc/c/c-typeck.c	(working copy)
@@ -8760,6 +8760,22 @@ output_init_element (location_t loc, tre
   if (!maybe_const)
     constructor_nonconst = 1;
 
+  /* Digest the initializer and issue any errors about incompatible
+     types before issuing errors about non-constant initializers.  */
+  tree new_value = value;
+  if (semantic_type)
+    new_value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
+  new_value = digest_init (loc, type, new_value, origtype, npc, strict_string,
+			   require_constant_value);
+  if (new_value == error_mark_node)
+    {
+      constructor_erroneous = 1;
+      return;
+    }
+  if (require_constant_value || require_constant_elements)
+    constant_expression_warning (new_value);
+
+  /* Proceed to check the constness of the original initializer.  */
   if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
     {
       if (require_constant_value)
@@ -8804,17 +8820,8 @@ output_init_element (location_t loc, tre
 		  || DECL_CHAIN (field)))))
     return;
 
-  if (semantic_type)
-    value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
-  value = digest_init (loc, type, value, origtype, npc, strict_string,
-		       require_constant_value);
-  if (value == error_mark_node)
-    {
-      constructor_erroneous = 1;
-      return;
-    }
-  if (require_constant_value || require_constant_elements)
-    constant_expression_warning (value);
+  /* Finally, set VALUE to the initializer value digested above.  */
+  value = new_value;
 
   /* If this element doesn't come next in sequence,
      put it on constructor_pending_elts.  */
Index: gcc/testsuite/gcc.dg/init-bad-9.c
===================================================================
--- gcc/testsuite/gcc.dg/init-bad-9.c	(revision 0)
+++ gcc/testsuite/gcc.dg/init-bad-9.c	(working copy)
@@ -0,0 +1,12 @@
+/* PR c/71552 - Confusing error for incorrect struct initialization */
+/* { dg-do compile } */
+
+struct A { void *p; };
+struct B { struct A *p; };
+struct A a;
+
+/* Verify that the initializer is diagnosed for its incompatibility
+   with the type of the object being initialized, not for its lack
+   of constness (which is a lesser problem).  */
+struct B b = { a };   /* { dg-error "incompatible types when initializing" } */
+struct B *p = a;      /* { dg-error "incompatible types when initializing" } */

Reply via email to