c-common.c (braced_list_to_string): Remove eval parameter.
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Sun, 2 Sep 2018 15:18:30 +0000 (15:18 +0000)
committerJeff Law <law@gcc.gnu.org>
Sun, 2 Sep 2018 15:18:30 +0000 (09:18 -0600)
* 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-decl.c (finish_decl): Call braced_list_to_string here ...
* c-parser.c (c_parser_declaration_or_fndef): ... instead of here.

* 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.

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

From-SVN: r264042

12 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/array-init.c [new file with mode: 0644]
gcc/testsuite/g++.dg/init/string2.C

index 5440b25..4129f24 100644 (file)
@@ -1,3 +1,9 @@
+2018-09-02  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.
+
 2018-08-27  David Malcolm  <dmalcolm@redhat.com>
 
        PR 87091
index 6a5d991..13ed65c 100644 (file)
@@ -8542,39 +8542,28 @@ maybe_add_include_fixit (rich_location *richloc, const char *header,
 }
 
 /* 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 (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
+    return 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 };  */
-  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
-  if (tree size = 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)));
+  unsigned HOST_WIDE_INT maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+  maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
 
-         /* Avoid converting initializers for zero-length arrays.  */
-         if (!maxelts)
-           return NULL_TREE;
-       }
-    }
-  else if (!nelts)
-    /* Avoid handling the undefined/erroneous case of an empty
-       initializer for an arrays with unspecified bound.  */
-    return NULL_TREE;
+  /* Avoid converting initializers for zero-length arrays.  */
+  if (!maxelts)
+    return ctor;
 
-  tree eltype = TREE_TYPE (type);
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
 
   auto_vec<char> str;
   str.reserve (nelts + 1);
@@ -8584,19 +8573,21 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
 
   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).  */
@@ -8604,11 +8595,14 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
       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)
        {
@@ -8616,18 +8610,17 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
          str.quick_grow_cleared (idx);
        }
 
-      if (idx > maxelts)
-       return NULL_TREE;
+      if (idx >= maxelts)
+       return ctor;
 
       str.safe_insert (idx, val);
     }
 
-  if (!nelts)
-    /* Append a nul for the empty initializer { }.  */
+  /* Append a nul string termination.  */
+  if (str.length () < maxelts)
     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 c5e2028..cc168e2 100644 (file)
@@ -1331,7 +1331,7 @@ extern void maybe_add_include_fixit (rich_location *, const char *, bool);
 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 51b706c..5c18f63 100644 (file)
@@ -1,3 +1,8 @@
+2018-09-02  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.
+
 2018-08-30  Alexander Monakov  <amonakov@ispras.ru>
 
        * gimple-parser.c (c_parser_gimple_binary_expression): Accept infix
index feafc02..fd08d72 100644 (file)
@@ -5031,6 +5031,12 @@ finish_decl (tree decl, location_t init_loc, tree init,
       relayout_decl (decl);
     }
 
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_STRING_FLAG (TREE_TYPE (type))
+      && DECL_INITIAL (decl)
+      && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
+    DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl));
+
   if (VAR_P (decl))
     {
       if (init && TREE_CODE (init) == CONSTRUCTOR)
index 28384df..69ed5ae 100644 (file)
@@ -2127,15 +2127,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
              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 9e135b3..cec14d5 100644 (file)
@@ -1,3 +1,10 @@
+2018-09-02  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.
+
 2018-08-31  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/87155
index d743e6f..5962c19 100644 (file)
@@ -6283,30 +6283,6 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
   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.
@@ -6422,17 +6398,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
            }
          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 71fbff1..7cd0a7e 100644 (file)
@@ -807,6 +807,11 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
     /* Digest the specified initializer into an expression.  */
     value = digest_init_flags (type, init, flags, tf_warning_or_error);
 
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_STRING_FLAG (TREE_TYPE (type))
+      && TREE_CODE (value) == CONSTRUCTOR)
+    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.
@@ -1058,9 +1063,7 @@ digest_init_r (tree type, tree init, int nested, int flags,
 
          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 83bab17..c192dcc 100644 (file)
@@ -1,3 +1,8 @@
+2018-09-02  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       * c-c++-common/array-init.c: New test.
+       * g++.dg/init/string2.C: Remove selector.
+
 2018-09-01  Michael Matz  <matz@suse.de>
 
        PR tree-optimization/87074
diff --git a/gcc/testsuite/c-c++-common/array-init.c b/gcc/testsuite/c-c++-common/array-init.c
new file mode 100644 (file)
index 0000000..0624e70
--- /dev/null
@@ -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 5da13bd..19ae6b4 100644 (file)
@@ -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);
 }