OSDN Git Service

* c-typeck.c (digest_init): Don't allow arrays of signed or
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Jul 2004 09:12:21 +0000 (09:12 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Jul 2004 09:12:21 +0000 (09:12 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85146 138bc75d-0d04-0410-961f-82ee72b054a4

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

index a6719d3..c5df482 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 d00f86c..2ed3c37 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 8c95159..7b0d645 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" };