This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Call braced_list_to_string after array size is fixed


Hi,

Yes I know Martin will see this as a capital offense, but to my excuse I must say
it only happened in self defense :-)

As my other patch series depends on STRNG_CSTs with certain properties, it got
broken by the way the string constants are created now, due to the 71625 patch.

In order to be able to bootstrap my patch with current trunk, I had to move
the point where the char array constructor is converted to a STRING_CST to the
point directly after the array bounds are fixed, so that it is possible to create
the string constant (with implicit NUL termination) like all other C strings, without
making the array larger.

I added a test case for a crash with an invalid string intializer (in C++).
and removed an xfail in the new test case string2.C.  This way the C++ diagnostics
matches the state before 71625 was applied.

This does not fix the other problems with 71625, but I don't think they are related
to the way the string constants are created, so there should be no conflict.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.
c-family:
2018-08-17  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-common.c (braced_list_to_string): Remove eval parameter.
	Add some more checks.  Always create zero-terminated STRING_CST.
	* c-common.h (braced_list_to_string): Adjust prototype.

c:
2018-08-17  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-decl.c (finish_decl): Call braced_list_to_string here ...
	* c-parser.c (c_parser_declaration_or_fndef): ... instead of here.


cp:
2018-08-17  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* decl.c (eval_check_narrowing): Remove.
	(check_initializer): Move call to braced_list_to_string from here ...
	* typeck2.c (store_init_value): ... to here.
	(digest_init_r): Remove handing of signed/unsigned char strings.

testsuite:
2018-08-17  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-c++-common/array-init.c: New test.
	* g++.dg/init/string2.C: Remove xfail.


Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 263554)
+++ gcc/c/c-decl.c	(working copy)
@@ -5011,6 +5011,17 @@ finish_decl (tree decl, location_t init_
       relayout_decl (decl);
     }
 
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && DECL_INITIAL (decl)
+      && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
+    {
+      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      if (typ1 == char_type_node
+	  || typ1 == signed_char_type_node
+	  || typ1 == unsigned_char_type_node)
+	DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl));
+    }
+
   if (VAR_P (decl))
     {
       if (init && TREE_CODE (init) == CONSTRUCTOR)
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 263554)
+++ gcc/c/c-parser.c	(working copy)
@@ -2126,15 +2126,6 @@ c_parser_declaration_or_fndef (c_parser
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
-
-		  /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
-		  tree valtype = TREE_TYPE (init.value);
-		  if (TREE_CODE (init.value) == CONSTRUCTOR
-		      && TREE_CODE (valtype) == ARRAY_TYPE
-		      && TYPE_STRING_FLAG (TREE_TYPE (valtype)))
-		    if (tree str = braced_list_to_string (valtype, init.value))
-		      init.value = str;
-
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263554)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8510,39 +8510,24 @@ maybe_add_include_fixit (rich_location *
 }
 
 /* Attempt to convert a braced array initializer list CTOR for array
-   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
-   use EVAL to attempt to evalue constants (used by C++).  Return
-   the converted string on success or null on failure.  */
+   TYPE into a STRING_CST for convenience and efficiency.  Return
+   the converted string on success or the original ctor on failure.  */
 
 tree
-braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
+braced_list_to_string (tree type, tree ctor)
 {
   unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
 
-  /* If the array has an explicit bound, use it to constrain the size
-     of the string.  If it doesn't, be sure to create a string that's
-     as long as implied by the index of the last zero specified via
-     a designator, as in:
-       const char a[] = { [7] = 0 };  */
+  /* When this function is called, the array has already an explicit bound,
+     but in the case of VLAs it can be a variable length.
+     See testsuite/g++.dg/ext/vla19.C for an example.
+     Allow this conversion to succeed in this case.  */
   unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
-  if (tree size = TYPE_SIZE_UNIT (type))
+  if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
     {
-      if (tree_fits_uhwi_p (size))
-	{
-	  maxelts = tree_to_uhwi (size);
-	  maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
-
-	  /* Avoid converting initializers for zero-length arrays.  */
-	  if (!maxelts)
-	    return NULL_TREE;
-	}
+      maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+      maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
     }
-  else if (!nelts)
-    /* Avoid handling the undefined/erroneous case of an empty
-       initializer for an arrays with unspecified bound.  */
-    return NULL_TREE;
-
-  tree eltype = TREE_TYPE (type);
 
   auto_vec<char> str;
   str.reserve (nelts + 1);
@@ -8552,19 +8537,21 @@ braced_list_to_string (tree type, tree c
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
     {
-      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+      unsigned HOST_WIDE_INT idx = i;
+      if (index)
+	{
+	  if (!tree_fits_uhwi_p (index))
+	    return ctor;
+	  idx = tree_to_uhwi (index);
+	}
 
       /* auto_vec is limited to UINT_MAX elements.  */
       if (idx > UINT_MAX)
-	return NULL_TREE;
+	return ctor;
 
-      /* Attempt to evaluate constants.  */
-      if (eval)
-	value = eval (eltype, value);
-
-      /* Avoid non-constant initializers.  */
+     /* Avoid non-constant initializers.  */
      if (!tree_fits_shwi_p (value))
-	return NULL_TREE;
+	return ctor;
 
       /* Skip over embedded nuls except the last one (initializer
 	 elements are in ascending order of indices).  */
@@ -8572,11 +8559,14 @@ braced_list_to_string (tree type, tree c
       if (!val && i + 1 < nelts)
 	continue;
 
+      if (idx < str.length())
+	return ctor;
+
       /* Bail if the CTOR has a block of more than 256 embedded nuls
 	 due to implicitly initialized elements.  */
       unsigned nchars = (idx - str.length ()) + 1;
       if (nchars > 256)
-	return NULL_TREE;
+	return ctor;
 
       if (nchars > 1)
 	{
@@ -8585,17 +8575,15 @@ braced_list_to_string (tree type, tree c
 	}
 
       if (idx > maxelts)
-	return NULL_TREE;
+	return ctor;
 
       str.safe_insert (idx, val);
     }
 
-  if (!nelts)
-    /* Append a nul for the empty initializer { }.  */
-    str.safe_push (0);
+  /* Append a nul string termination.  */
+  str.safe_push (0);
 
-  /* Build a STRING_CST with the same type as the array, which
-     may be an array of unknown bound.  */
+  /* Build a STRING_CST with the same type as the array */
   tree res = build_string (str.length (), str.begin ());
   TREE_TYPE (res) = type;
   return res;
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 263554)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1331,7 +1331,7 @@ extern void maybe_add_include_fixit (ric
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
-extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL);
+extern tree braced_list_to_string (tree, tree);
 
 #if CHECKING_P
 namespace selftest {
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 263554)
+++ gcc/cp/decl.c	(working copy)
@@ -6282,30 +6282,6 @@ build_aggr_init_full_exprs (tree decl, t
   return build_aggr_init (decl, init, flags, tf_warning_or_error);
 }
 
-/* Attempt to determine the constant VALUE of integral type and convert
-   it to TYPE, issuing narrowing warnings/errors as necessary.  Return
-   the constant result or null on failure.  Callback for
-   braced_list_to_string.  */
-
-static tree
-eval_check_narrowing (tree type, tree value)
-{
-  if (tree valtype = TREE_TYPE (value))
-    {
-      if (TREE_CODE (valtype) != INTEGER_TYPE)
-	return NULL_TREE;
-    }
-  else
-    return NULL_TREE;
-
-  value = scalar_constant_value (value);
-  if (!value)
-    return NULL_TREE;
-
-  check_narrowing (type, value, tf_warning_or_error);
-  return value;
-}
-
 /* Verify INIT (the initializer for DECL), and record the
    initialization in DECL_INITIAL, if appropriate.  CLEANUP is as for
    grok_reference_init.
@@ -6421,17 +6397,7 @@ check_initializer (tree decl, tree init,
 	    }
 	  else
 	    {
-	      /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
-	      tree valtype = TREE_TYPE (decl);
-	      if (TREE_CODE (valtype) == ARRAY_TYPE
-		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
-		  && BRACE_ENCLOSED_INITIALIZER_P (init))
-		if (tree str = braced_list_to_string (valtype, init,
-						      eval_check_narrowing))
-		  init = str;
-
-	      if (TREE_CODE (init) != STRING_CST)
-		init = reshape_init (type, init, tf_warning_or_error);
+	      init = reshape_init (type, init, tf_warning_or_error);
 	      flags |= LOOKUP_NO_NARROWING;
 	    }
 	}
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	(revision 263554)
+++ gcc/cp/typeck2.c	(working copy)
@@ -813,6 +813,16 @@ store_init_value (tree decl, tree init, vec<tree,
     /* Digest the specified initializer into an expression.  */
     value = digest_init_flags (type, init, flags, tf_warning_or_error);
 
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (value) == CONSTRUCTOR)
+    {
+      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      if (typ1 == char_type_node
+	 || typ1 == signed_char_type_node
+	 || typ1 == unsigned_char_type_node)
+	value = braced_list_to_string (type, value);
+    }
+
   value = extend_ref_init_temps (decl, value, cleanups);
 
   /* In C++11 constant expression is a semantic, not syntactic, property.
@@ -1056,9 +1066,7 @@ digest_init_r (tree type, tree init, int
 
 	  if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
 	    {
-	      if (char_type != char_type_node
-		  && char_type != signed_char_type_node
-		  && char_type != unsigned_char_type_node)
+	      if (char_type != char_type_node)
 		{
 		  if (complain & tf_error)
 		    error_at (loc, "char-array initialized from wide string");
Index: gcc/testsuite/c-c++-common/array-init.c
===================================================================
--- gcc/testsuite/c-c++-common/array-init.c	(revision 0)
+++ gcc/testsuite/c-c++-common/array-init.c	(working copy)
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-prune-output "sorry, unimplemented: non-trivial designated initializers not supported" } */
+
+char x[] = { [-1] = 1, 2, 3 }; /* { dg-error "array index in initializer exceeds array bounds" "" { target c } } */
Index: gcc/testsuite/g++.dg/init/string2.C
===================================================================
--- gcc/testsuite/g++.dg/init/string2.C	(revision 263554)
+++ gcc/testsuite/g++.dg/init/string2.C	(working copy)
@@ -54,7 +54,7 @@ template <class T>
 int tmplen ()
 {
   static const T
-    a[] = { 1, 2, 333, 0 };         // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+    a[] = { 1, 2, 333, 0 };         // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" }
   return __builtin_strlen (a);
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]