diff mbox series

ping [PATCH] c++: fix string literal member initializer bug [PR90926]

Message ID SN6PR11MB3022C6326F635D6A512C2D48CBA10@SN6PR11MB3022.namprd11.prod.outlook.com
State New
Headers show
Series ping [PATCH] c++: fix string literal member initializer bug [PR90926] | expand

Commit Message

Tom Greenslade \(thomgree\) Jan. 21, 2021, 6:05 p.m. UTC
Ping for this patch:
https://gcc.gnu.org/pipermail/gcc-patches/2020-December/562259.html

-----Original Message-----
From: Thomas Greenslade (thomgree) 
Sent: 17 December 2020 22:12
To: gcc-patches@gcc.gnu.org
Subject: [PATCH] c++: fix string literal member initializer bug [PR90926]

build_aggr_conv did not correctly handle string literal member initializers. 
Extended can_convert_array to handle this case. The additional checks of compatibility of character types, and whether string literal will fit, would be quite complicated, so are deferred until the actual conversion takes place.

Testcase added for this.

Bootstrapped/regtested on x86_64-pc-linux-gnu.

gcc/cp/ChangeLog:

	PR c++/90926
	* call.c (can_convert_array): Extend to handle all valid aggregate
	initializers of an array; including by string literals, not just by
	brace-init-list.
	(build_aggr_conv): Call can_convert_array more often, not just in
	brace-init-list case.
	* g++.dg/cpp1y/nsdmi-aggr12.C: New test.
diff mbox series

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c2d62e582bf..e4ba31f3f2b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -887,28 +887,41 @@  strip_standard_conversion (conversion *conv)
   return conv;
 }
 
-/* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list,
-   is a valid aggregate initializer for array type ATYPE.  */
+/* Subroutine of build_aggr_conv: check whether FROM is a valid aggregate
+   initializer for array type ATYPE.  */
 
 static bool
-can_convert_array (tree atype, tree ctor, int flags, tsubst_flags_t complain)
+can_convert_array (tree atype, tree from, int flags, tsubst_flags_t 
+complain)
 {
-  unsigned i;
   tree elttype = TREE_TYPE (atype);
-  for (i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
+  unsigned i;
+
+  if (TREE_CODE (from) == CONSTRUCTOR)
     {
-      tree val = CONSTRUCTOR_ELT (ctor, i)->value;
-      bool ok;
-      if (TREE_CODE (elttype) == ARRAY_TYPE
-	  && TREE_CODE (val) == CONSTRUCTOR)
-	ok = can_convert_array (elttype, val, flags, complain);
-      else
-	ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags,
-			      complain);
-      if (!ok)
-	return false;
+      for (i = 0; i < CONSTRUCTOR_NELTS (from); ++i)
+	{
+	  tree val = CONSTRUCTOR_ELT (from, i)->value;
+	  bool ok;
+	  if (TREE_CODE (elttype) == ARRAY_TYPE)
+	    ok = can_convert_array (elttype, val, flags, complain);
+	  else
+	    ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags,
+				  complain);
+	  if (!ok)
+	    return false;
+	}
+      return true;
     }
-  return true;
+
+  if (   char_type_p (TYPE_MAIN_VARIANT (elttype))
+      && TREE_CODE (tree_strip_any_location_wrapper (from)) == STRING_CST)
+    /* Defer the other necessary checks (compatibility of character types and
+       whether string literal will fit) until the conversion actually takes
+       place.  */
+    return true;
+
+  /* No other valid way to aggregate initialize an array.  */  return 
+ false;
 }
 
 /* Helper for build_aggr_conv.  Return true if FIELD is in PSET, or if @@ -965,8 +978,7 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
 	      tree ftype = TREE_TYPE (idx);
 	      bool ok;
 
-	      if (TREE_CODE (ftype) == ARRAY_TYPE
-		  && TREE_CODE (val) == CONSTRUCTOR)
+	      if (TREE_CODE (ftype) == ARRAY_TYPE)
 		ok = can_convert_array (ftype, val, flags, complain);
 	      else
 		ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags, @@ -1013,9 +1025,8 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
 	  val = empty_ctor;
 	}
 
-      if (TREE_CODE (ftype) == ARRAY_TYPE
-	  && TREE_CODE (val) == CONSTRUCTOR)
-	ok = can_convert_array (ftype, val, flags, complain);
+      if (TREE_CODE (ftype) == ARRAY_TYPE)
+	ok = can_convert_array (ftype, val, flags, complain);
       else
 	ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags,
 			      complain);
diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C
new file mode 100644
index 00000000000..ce8c95e8aca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C
@@ -0,0 +1,21 @@ 
+// PR c++/90926
+// { dg-do run { target c++14 } }
+
+struct A
+{
+  char str[4] = "foo";
+  char str_array[2][4] = {"bar", "baz"}; };
+
+int
+main ()
+{
+  A a;
+  a.str[0] = 'g';
+  a.str_array[0][0] = 'g';
+  a = {};
+  if (__builtin_strcmp (a.str, "foo") != 0)
+    __builtin_abort();
+  if (__builtin_strcmp (a.str_array[0], "bar") != 0)
+    __builtin_abort();
+}