diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 947bbfc6637..f01655c5c14 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6820,6 +6820,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
     {
       tree str_init = init;
       tree stripped_str_init = stripped_init;
+      reshape_iter stripd = {};
 
       /* Strip one level of braces if and only if they enclose a single
 	 element (as allowed by [dcl.init.string]).  */
@@ -6827,7 +6828,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
 	  && TREE_CODE (stripped_str_init) == CONSTRUCTOR
 	  && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
 	{
-	  str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+	  stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0);
+	  str_init = stripd.cur->value;
 	  stripped_str_init = tree_strip_any_location_wrapper (str_init);
 	}
 
@@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
 	 array types (one value per array element).  */
       if (TREE_CODE (stripped_str_init) == STRING_CST)
 	{
-	  if (has_designator_problem (d, complain))
+	  if ((first_initializer_p && has_designator_problem (d, complain))
+	      || (stripd.cur && has_designator_problem (&stripd, complain)))
 	    return error_mark_node;
 	  d->cur++;
 	  return str_init;
@@ -9538,23 +9541,10 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
   if (initial_value)
     {
-      /* An array of character type can be initialized from a
-	 brace-enclosed string constant.
-
-	 FIXME: this code is duplicated from reshape_init. Probably
-	 we should just call reshape_init here?  */
-      if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
-	  && TREE_CODE (initial_value) == CONSTRUCTOR
-	  && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
-	{
-	  vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
-	  tree value = (*v)[0].value;
-	  STRIP_ANY_LOCATION_WRAPPER (value);
-
-	  if (TREE_CODE (value) == STRING_CST
-	      && v->length () == 1)
-	    initial_value = value;
-	}
+      if (TREE_CODE (initial_value) == CONSTRUCTOR
+	  && BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+	initial_value = reshape_init (*ptype, initial_value,
+				      tf_warning_or_error);
 
       /* If any of the elements are parameter packs, we can't actually
 	 complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 00000000000..03eab764325
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,48 @@
+// PR c++/55227 
+// Test designated initializer for char array by string constant
+
+// { dg-do compile }
+// { dg-options "-pedantic" }
+
+struct C {char a[2];};
+
+/* Case a; designated, unbraced, string-literal of the same size as the target
+   char array to be initialized; valid and accepted before and after.  */
+
+C a = {.a="a"}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 }
+
+/* Cases b,c,d; designated mismatched-size string literal, or designated braced
+   string literal (of any size less than or equal to the target char array),
+   previously rejected ("C99 designator 'a' outside aggregate initializer").  */
+
+C b = {.a=""}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 }
+C c = {.a={""}}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 }
+C d = {.a={"a"}}; // { dg-warning "designated initializers only available with" "" { target c++17_down } .-0 }
+
+/* Case e; designated char array field and braced, designated array element(s)
+   (with GNU [N]= extension) valid extension, accepted before and after.  */
+
+C e = {.a={[0]='a'}}; // { dg-warning "ISO C.. does not allow C99 designated initializers" }
+// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 }
+
+/* Cases f,g,h; braced string literal, 'designated' within inner braces;
+   invalid, previously accepted as positional with 'designator' ignored.  */
+   
+C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate initializer" }
+// { dg-warning "ISO C.. does not allow C99 designated initializers" "C99 desig" { target *-*-* } .-1 }
+C g = {{.a="a"}}; // { dg-error "C99 designator .a. outside aggregate initializer" }
+// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 }
+C h = {{.b="a"}}; // { dg-error "C99 designator .b. outside aggregate initializer" }
+// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 }
+
+template <class T>
+void t()
+{
+  C ca[] = { {.a=""}, {.a={""}}, };
+// { dg-warning "designated initializers only available with" "" { target c++17_down } .-1 }
+}
+
+void u()
+{
+  return t<void>();
+}
