c-typeck.c (digest_init): Don't allow arrays of signed or unsigned variants of wchar_...
authorJoseph Myers <jsm@polyomino.org.uk>
Sun, 25 Jul 2004 09:12:21 +0000 (10:12 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Sun, 25 Jul 2004 09:12:21 +0000 (10:12 +0100)
* c-typeck.c (digest_init): Don't allow arrays of signed or
unsigned variants of wchar_t to be initialized by wide string
constants.  Do allow arrays of enumerated types compatible with
wchar_t to be initialized by wide string constants.  Refine tests
distinguishing wide and narrow strings and arrays.  Give specific
error for arrays of other integer types initialized by string
constants.
(output_init_element, process_init_element): Check for
INTEGRAL_TYPE_P rather than just for INTEGER_TYPE when
initializing with string constants.

testsuite:
* gcc.dg/init-string-2.c: New test.

From-SVN: r85146

gcc/ChangeLog
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/init-string-2.c [new file with mode: 0644]

index a6719d35b020fcd34fb4ce4e976e6cc438d74c13..c5df482fb738d04453b5e5225a76395d85d50809 100644 (file)
@@ -1,3 +1,16 @@
+2004-07-25  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * c-typeck.c (digest_init): Don't allow arrays of signed or
+       unsigned variants of wchar_t to be initialized by wide string
+       constants.  Do allow arrays of enumerated types compatible with
+       wchar_t to be initialized by wide string constants.  Refine tests
+       distinguishing wide and narrow strings and arrays.  Give specific
+       error for arrays of other integer types initialized by string
+       constants.
+       (output_init_element, process_init_element): Check for
+       INTEGRAL_TYPE_P rather than just for INTEGER_TYPE when
+       initializing with string constants.
+
 2004-07-25  Richard Henderson  <rth@redhat.com>
 
        * c-decl.c (start_function): Set DECL_ARTIFICIAL and DECL_IGNORED_P
index d00f86c8e043851700e2c180b5a2ba6e089c6afb..2ed3c379a0fe71073c468c0ce75db95da0df548c 100644 (file)
@@ -3930,37 +3930,41 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
 
-  if (code == ARRAY_TYPE)
+  if (code == ARRAY_TYPE && inside_init
+      && TREE_CODE (inside_init) == STRING_CST)
     {
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if ((typ1 == char_type_node
-          || typ1 == signed_char_type_node
-          || typ1 == unsigned_char_type_node
-          || typ1 == unsigned_wchar_type_node
-          || typ1 == signed_wchar_type_node)
-         && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
+      /* Note that an array could be both an array of character type
+        and an array of wchar_t if wchar_t is signed char or unsigned
+        char.  */
+      bool char_array = (typ1 == char_type_node
+                        || typ1 == signed_char_type_node
+                        || typ1 == unsigned_char_type_node);
+      bool wchar_array = !!comptypes (typ1, wchar_type_node);
+      if (char_array || wchar_array)
        {
          struct c_expr expr;
+         bool char_string;
          expr.value = inside_init;
          expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
          maybe_warn_string_init (type, expr);
 
+         char_string
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
+              == char_type_node);
+
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                         TYPE_MAIN_VARIANT (type)))
            return inside_init;
 
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              != char_type_node)
-             && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
+         if (!wchar_array && !char_string)
            {
              error_init ("char-array initialized from wide string");
              return error_mark_node;
            }
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              == char_type_node)
-             && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
+         if (char_string && !char_array)
            {
-             error_init ("int-array initialized from non-wide string");
+             error_init ("wchar_t-array initialized from non-wide string");
              return error_mark_node;
            }
 
@@ -3982,6 +3986,12 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
          return inside_init;
        }
+      else if (INTEGRAL_TYPE_P (typ1))
+       {
+         error_init ("array of inappropriate type initialized "
+                     "from string constant");
+         return error_mark_node;
+       }
     }
 
   /* Build a VECTOR_CST from a *constant* vector constructor.  If the
@@ -5476,7 +5486,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
          && !(TREE_CODE (value) == STRING_CST
               && TREE_CODE (type) == ARRAY_TYPE
-              && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+              && INTEGRAL_TYPE_P (TREE_TYPE (type)))
          && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
                         TYPE_MAIN_VARIANT (type))))
     value = default_conversion (value);
@@ -5776,7 +5786,7 @@ process_init_element (struct c_expr value)
   if (string_flag
       && constructor_type
       && TREE_CODE (constructor_type) == ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
+      && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
@@ -5855,7 +5865,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
@@ -5943,7 +5953,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
@@ -5983,7 +5993,7 @@ process_init_element (struct c_expr value)
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
              && eltcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (elttype))
              && string_flag)
            value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
index 8c9515942eb1c7d792b1b4b97b013a85426c4064..7b0d645b8a3fb8de41aaf4deb76de96a50d5aa20 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-25  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * gcc.dg/init-string-2.c: New test.
+
 2004-07-24  Zack Weinberg  <zack@codesourcery.com>
 
        PR 16684
diff --git a/gcc/testsuite/gcc.dg/init-string-2.c b/gcc/testsuite/gcc.dg/init-string-2.c
new file mode 100644 (file)
index 0000000..828897b
--- /dev/null
@@ -0,0 +1,56 @@
+/* Character arrays but not arrays of compatible enum type may be
+   initialized by narrow string literals.  Arrays of type compatible
+   with wchar_t, including compatible enums, may be initialized by
+   wide string literals.  Use -fshort-enums -fshort-wchar so the
+   relevant circumstances can be obtained portably; may still fail if
+   char, short and int do not all have distinct precisions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors -fshort-enums -fshort-wchar" } */
+
+#include <limits.h>
+#include <stddef.h>
+
+typedef enum { schar_min = SCHAR_MIN, schar_max = SCHAR_MAX } schar;
+typedef enum { uchar_max = UCHAR_MAX } uchar;
+typedef enum { shrt_min = SHRT_MIN, shrt_max = SHRT_MAX } sshrt;
+typedef enum { ushrt_max = USHRT_MAX } ushrt;
+
+char a0[] = "foo";
+const signed char a2[4] = "foo";
+volatile unsigned char a3[3] = "foo";
+wchar_t a4[] = L"foo";
+const wchar_t a5[3] = L"foo";
+volatile ushrt a6[] = L"foo";
+
+schar a7[] = "foo"; /* { dg-error "string constant" "a7" } */
+uchar a8[] = "foo"; /* { dg-error "string constant" "a8" } */
+const schar a9[] = "foo"; /* { dg-error "string constant" "a9" } */
+short a10[] = L"foo"; /* { dg-error "string constant" "a10" } */
+const sshrt a11[] = L"foo"; /* { dg-error "string constant" "a11" } */
+char a12[] = L"foo"; /* { dg-error "from wide string" "a12" } */
+wchar_t a13[] = "foo"; /* { dg-error "non-wide string" "a13" } */
+
+char b0[] = { "foo" };
+const signed char b2[4] = { "foo" };
+volatile unsigned char b3[3] = { "foo" };
+wchar_t b4[] = { L"foo" };
+const wchar_t b5[3] = { L"foo" };
+volatile ushrt b6[] = { L"foo" };
+
+schar b7[] = { "foo" }; /* { dg-error "string constant" "b7" } */
+uchar b8[] = { "foo" }; /* { dg-error "string constant" "b8" } */
+const schar b9[] = { "foo" }; /* { dg-error "string constant" "b9" } */
+short b10[] = { L"foo" }; /* { dg-error "string constant" "b10" } */
+const sshrt b11[] = { L"foo" }; /* { dg-error "string constant" "b11" } */
+char b12[] = { L"foo" }; /* { dg-error "from wide string" "b12" } */
+wchar_t b13[] = { "foo" }; /* { dg-error "non-wide string" "b13" } */
+
+struct s { signed char a[10]; int b; ushrt c[10]; };
+
+struct s c = { "foo", 0, L"bar" };
+struct s d = { .c = L"bar", .a = "foo" };
+
+ushrt *e = (ushrt [7]){ L"bar" };
+
+wchar_t f[5][5] = { L"foo", L"bar" };
+ushrt g[5][5] = { L"foo", L"bar" };