diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 9ac1fea31791ee5a3b468ab323ec2f84e7af40eb..691b583db3f85eeb5d640711b797c6756dfa890d 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -10270,7 +10270,8 @@ pop_init_level (location_t loc, int implicit,
 	  gcc_assert (!TYPE_SIZE (constructor_type));
 
 	  if (constructor_depth > 2)
-	    error_init (loc, "initialization of flexible array member in a nested context");
+	    error_init (loc, "initialization of flexible array member "
+			     "in a nested context");
 	  else
 	    pedwarn_init (loc, OPT_Wpedantic,
 			  "initialization of a flexible array member");
@@ -10278,7 +10279,8 @@ pop_init_level (location_t loc, int implicit,
 	  /* We have already issued an error message for the existence
 	     of a flexible array member not at the end of the structure.
 	     Discard the initializer so that we do not die later.  */
-	  if (DECL_CHAIN (constructor_fields) != NULL_TREE)
+	  if (DECL_CHAIN (constructor_fields) != NULL_TREE
+	      && (!p->type || TREE_CODE (p->type) != UNION_TYPE))
 	    constructor_type = NULL_TREE;
 	}
     }
@@ -12124,6 +12126,42 @@ retry:
 	    warning (OPT_Wtraditional, "traditional C rejects initialization "
 		     "of unions");
 
+	  /* Error for non-static initialization of a flexible array member.  */
+	  if (fieldcode == ARRAY_TYPE
+	      && !require_constant_value
+	      && TYPE_SIZE (fieldtype) == NULL_TREE)
+	    {
+	      error_init (loc, "non-static initialization of a flexible "
+			  "array member");
+	      break;
+	    }
+
+	  /* Error for initialization of a flexible array member with
+	     a string constant if the structure is in an array.  E.g.:
+	     union U { int x; char y[]; };
+	     union U s[] = { { 1, "foo" } };
+	     is invalid.  */
+	  if (string_flag
+	      && fieldcode == ARRAY_TYPE
+	      && constructor_depth > 1
+	      && TYPE_SIZE (fieldtype) == NULL_TREE)
+	    {
+	      bool in_array_p = false;
+	      for (struct constructor_stack *p = constructor_stack;
+		   p && p->type; p = p->next)
+		if (TREE_CODE (p->type) == ARRAY_TYPE)
+		  {
+		    in_array_p = true;
+		    break;
+		  }
+	      if (in_array_p)
+		{
+		  error_init (loc, "initialization of flexible array "
+			      "member in a nested context");
+		  break;
+		}
+	    }
+
 	  /* Accept a string constant to initialize a subarray.  */
 	  if (value.value != NULL_TREE
 	      && fieldcode == ARRAY_TYPE
diff --git a/gcc/testsuite/gcc.dg/pr119001-1.c b/gcc/testsuite/gcc.dg/pr119001-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..22ceca9da77d3ba213d32473fe3ab24f6fa407aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119001-1.c
@@ -0,0 +1,35 @@
+/* PR c/119001 */
+/* { dg-do run } */
+/* { dg-options "" } */
+
+union U { char a[]; int i; };
+union U u = { "12345" };
+union U v = { .a = "6789" };
+union U w = { { 1, 2, 3, 4, 5, 6 } };
+union U x = { .a = { 7, 8, 9 } };
+union V { int i; char a[]; };
+union V y = { .a = "abcdefghijk" };
+union V z = { .a = { 10, 11, 12, 13, 14, 15, 16, 17 } };
+
+int
+main ()
+{
+  for (int i = 0; i < 6; ++i)
+    if (u.a[i] != "12345"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 5; ++i)
+    if (v.a[i] != "6789"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 6; ++i)
+    if (w.a[i] != i + 1)
+      __builtin_abort ();
+  for (int i = 0; i < 3; ++i)
+    if (x.a[i] != i + 7)
+      __builtin_abort ();
+  for (int i = 0; i < 12; ++i)
+    if (y.a[i] != "abcdefghijk"[i])
+      __builtin_abort ();
+  for (int i = 0; i < 8; ++i)
+    if (z.a[i] != i + 10)
+      __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr119001-2.c b/gcc/testsuite/gcc.dg/pr119001-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..b95fd0d1198e4bf09484bf8ce77fd7fbdda4d2ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119001-2.c
@@ -0,0 +1,20 @@
+/* PR c/119001 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+union U { char a[]; int i; };
+union U u[1] = { { "12345" } };			/* { dg-error "initialization of flexible array member in a nested context" } */
+union U v[1] = { { .a = "6789" } };		/* { dg-error "initialization of flexible array member in a nested context" } */
+union U w[1] = { { { 1, 2, 3, 4, 5, 6 } } };	/* { dg-error "initialization of flexible array member in a nested context" } */
+union U x[1] = { { .a = { 7, 8, 9 } } };	/* { dg-error "initialization of flexible array member in a nested context" } */
+union V { int i; char a[]; };
+union V y[1] = { { .a = "6789" } };		/* { dg-error "initialization of flexible array member in a nested context" } */
+union V z[1] = { { .a = { 7, 8, 9 } } };	/* { dg-error "initialization of flexible array member in a nested context" } */
+
+void
+foo (int x)
+{
+  union U a = { { x, x + 1 } };			/* { dg-error "non-static initialization of a flexible array member" } */
+  union U b = { .a = { x + 2, x + 3 } };	/* { dg-error "non-static initialization of a flexible array member" } */
+  union V c = { .a = { x + 4, x + 5 } };	/* { dg-error "non-static initialization of a flexible array member" } */
+}
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index 6d93fe97d7bf67b75dc41ef0b994332e5392f587..eddfb6a3524d10c02c9fdecfdfa90633dd3659f4 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -5827,10 +5827,13 @@ output_constructor_regular_field (oc_local_state *local)
 	     and the FE splits them into dynamic initialization.  */
 	  gcc_checking_assert (fieldsize >= fldsize);
 	  /* Given a non-empty initialization, this field had better
-	     be last.  Given a flexible array member, the next field
-	     on the chain is a TYPE_DECL of the enclosing struct.  */
+	     be last except in unions.  Given a flexible array member, the next
+	     field on the chain is a TYPE_DECL of the enclosing struct.  */
 	  const_tree next = DECL_CHAIN (local->field);
-	  gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
+	  gcc_assert (!fieldsize
+		      || !next
+		      || TREE_CODE (next) != FIELD_DECL
+		      || TREE_CODE (local->type) == UNION_TYPE);
 	}
       else
 	fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));