re PR c/11250 (-pedantic accepts `char a[] = ("x");')
authorJoseph Myers <jsm@polyomino.org.uk>
Wed, 21 Jul 2004 23:46:20 +0000 (00:46 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 21 Jul 2004 23:46:20 +0000 (00:46 +0100)
PR c/11250
* c-parse.in (init): Change to exprtype.
(primary): Set original_code for STRING to STRING_CST.
Call maybe_warn_string_init for compound literals.
(initdcl, notype_initdcl): Call maybe_warn_string_init.
(initval): Update.
* c-tree.h (maybe_warn_string_init): New.
(pop_init_level, process_init_element): Use struct c_expr.
(struct c_expr): Update comment.
* c-typeck.c (maybe_warn_string_init): New function.
(digest_init): Call it.  Additional parameter strict_string.  All
callers changed.
(output_init_element): Likewise.
(struct constructor_stack): Use struct c_expr for
replacement_value.
(really_start_incremental_init, push_init_level): Update.
(pop_init_level): Update.  Return struct c_expr.
(process_init_level): Update.  Take struct c_expr argument.

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

From-SVN: r85022

gcc/ChangeLog
gcc/c-parse.in
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/init-string-1.c [new file with mode: 0644]

index 40ebced760984b1a4af735670a0c882ebc6658d9..16fa6573ca820c1a9eae3d8f5cff66e3c36fa18f 100644 (file)
@@ -1,3 +1,24 @@
+2004-07-22  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       PR c/11250
+       * c-parse.in (init): Change to exprtype.
+       (primary): Set original_code for STRING to STRING_CST.
+       Call maybe_warn_string_init for compound literals.
+       (initdcl, notype_initdcl): Call maybe_warn_string_init.
+       (initval): Update.
+       * c-tree.h (maybe_warn_string_init): New.
+       (pop_init_level, process_init_element): Use struct c_expr.
+       (struct c_expr): Update comment.
+       * c-typeck.c (maybe_warn_string_init): New function.
+       (digest_init): Call it.  Additional parameter strict_string.  All
+       callers changed.
+       (output_init_element): Likewise.
+       (struct constructor_stack): Use struct c_expr for
+       replacement_value.
+       (really_start_incremental_init, push_init_level): Update.
+       (pop_init_level): Update.  Return struct c_expr.
+       (process_init_level): Update.  Take struct c_expr argument.
+
 2004-07-21  David S. Miller  <davem@nuts.davemloft.net>
 
        * config/sparc/sparc.c (sparc_rtx_costs): Fix typo in previous
index b56bfee03ac535bb723c7d7aaf87cf1e0f3c2c1a..4179243f24070c92526773d308eff4774e14ed4a 100644 (file)
@@ -204,7 +204,8 @@ do {                                                                        \
 %type <ttype> offsetof_member_designator
 
 %type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
-%type <ttype> initdecls notype_initdecls initdcl notype_initdcl init
+%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
+%type <exprtype> init
 %type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
@@ -631,7 +632,7 @@ primary:
        | CONSTANT
                { $$.value = $1; $$.original_code = ERROR_MARK; }
        | STRING
-               { $$.value = $1; $$.original_code = ERROR_MARK; }
+               { $$.value = $1; $$.original_code = STRING_CST; }
        | FUNC_NAME
                { $$.value = fname_decl (C_RID_CODE ($1), $1);
                  $$.original_code = ERROR_MARK; }
@@ -640,9 +641,11 @@ primary:
                  $2 = groktypename ($2);
                  really_start_incremental_init ($2); }
          initlist_maybe_comma '}'  %prec UNARY
-               { tree constructor = pop_init_level (0);
+               { struct c_expr init = pop_init_level (0);
+                 tree constructor = init.value;
                  tree type = $2;
                  finish_init ();
+                 maybe_warn_string_init (type, init);
 
                  if (pedantic && ! flag_isoc99)
                    pedwarn ("ISO C90 forbids compound literals");
@@ -1391,7 +1394,8 @@ initdcl:
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
                { finish_init ();
-                 finish_decl ($<ttype>5, $6, $2); }
+                 maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
+                 finish_decl ($<ttype>5, $6.value, $2); }
        | declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, 0,
                                       chainon ($3, all_prefix_attributes));
@@ -1407,7 +1411,8 @@ notype_initdcl:
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
                { finish_init ();
-                 finish_decl ($<ttype>5, $6, $2); }
+                 maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6);
+                 finish_decl ($<ttype>5, $6.value, $2); }
        | notype_declarator maybeasm maybe_attribute
                { tree d = start_decl ($1, current_declspecs, 0,
                                       chainon ($3, all_prefix_attributes));
@@ -1476,13 +1481,13 @@ scspec:
 
 init:
        expr_no_commas
-               { $$ = $1.value; }
+               { $$ = $1; }
        | '{'
                { really_start_incremental_init (NULL_TREE); }
          initlist_maybe_comma '}'
                { $$ = pop_init_level (0); }
        | error
-               { $$ = error_mark_node; }
+               { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
        ;
 
 /* `initlist_maybe_comma' is the guts of an initializer in braces.  */
@@ -1522,7 +1527,7 @@ initval:
          initlist_maybe_comma '}'
                { process_init_element (pop_init_level (0)); }
        | expr_no_commas
-               { process_init_element ($1.value); }
+               { process_init_element ($1); }
        | error
        ;
 
index d6cdc97be13be270951aff337468c3b286502fa0..9e249532a5e38be4e91bbbea808dceca602bd865 100644 (file)
@@ -119,8 +119,9 @@ struct c_expr
   /* The value of the expression.  */
   tree value;
   /* Record the original binary operator of an expression, which may
-     have been changed by fold, or ERROR_MARK for other expressions
-     (including parenthesized expressions).  */
+     have been changed by fold, STRING_CST for unparenthesised string
+     constants, or ERROR_MARK for other expressions (including
+     parenthesized expressions).  */
   enum tree_code original_code;
 };
 
@@ -244,14 +245,15 @@ extern tree build_modify_expr (tree, enum tree_code, tree);
 extern void store_init_value (tree, tree);
 extern void error_init (const char *);
 extern void pedwarn_init (const char *);
+extern void maybe_warn_string_init (tree, struct c_expr);
 extern void start_init (tree, tree, int);
 extern void finish_init (void);
 extern void really_start_incremental_init (tree);
 extern void push_init_level (int);
-extern tree pop_init_level (int);
+extern struct c_expr pop_init_level (int);
 extern void set_init_index (tree, tree);
 extern void set_init_label (tree);
-extern void process_init_element (tree);
+extern void process_init_element (struct c_expr);
 extern tree build_compound_literal (tree, tree);
 extern void pedwarn_c90 (const char *, ...) ATTRIBUTE_PRINTF_1;
 extern void pedwarn_c99 (const char *, ...) ATTRIBUTE_PRINTF_1;
index 6e1b9281b63969e7f3501a938c11a19957dbb4e7..9c22b8b0cf0d7f85ad625ebf9c8f8f8bc9655486 100644 (file)
@@ -72,8 +72,8 @@ static void push_array_bounds (int);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (const char *);
-static tree digest_init (tree, tree, int);
-static void output_init_element (tree, tree, tree, int);
+static tree digest_init (tree, tree, bool, int);
+static void output_init_element (tree, bool, tree, tree, int);
 static void output_pending_init_elements (int);
 static int set_designator (int);
 static void push_range_stack (tree);
@@ -2960,7 +2960,7 @@ build_c_cast (tree type, tree expr)
          t = digest_init (type,
                           build_constructor (type,
                                              build_tree_list (field, value)),
-                          0);
+                          true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          TREE_INVARIANT (t) = TREE_INVARIANT (value);
          return t;
@@ -3674,7 +3674,7 @@ store_init_value (tree decl, tree init)
 
   /* Digest the specified initializer into an expression.  */
 
-  value = digest_init (type, init, TREE_STATIC (decl));
+  value = digest_init (type, init, true, TREE_STATIC (decl));
 
   /* Store the expression if valid; else report error.  */
 
@@ -3884,14 +3884,32 @@ warning_init (const char *msgid)
     warning ("(near initialization for `%s')", ofwhat);
 }
 \f
+/* If TYPE is an array type and EXPR is a parenthesized string
+   constant, warn if pedantic that EXPR is being used to initialize an
+   object of type TYPE.  */
+
+void
+maybe_warn_string_init (tree type, struct c_expr expr)
+{
+  if (pedantic
+      && TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (expr.value) == STRING_CST
+      && expr.original_code != STRING_CST)
+    pedwarn_init ("array initialized from parenthesized string constant");
+}
+
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
 
+   If INIT is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of INIT, STRICT_STRING is not used.
+
    REQUIRE_CONSTANT requests an error if non-constant initializers or
    elements are seen.  */
 
 static tree
-digest_init (tree type, tree init, int require_constant)
+digest_init (tree type, tree init, bool strict_string, int require_constant)
 {
   enum tree_code code = TREE_CODE (type);
   tree inside_init = init;
@@ -3922,6 +3940,11 @@ digest_init (tree type, tree init, int require_constant)
           || typ1 == signed_wchar_type_node)
          && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
        {
+         struct c_expr expr;
+         expr.value = inside_init;
+         expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
+         maybe_warn_string_init (type, expr);
+
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                         TYPE_MAIN_VARIANT (type)))
            return inside_init;
@@ -4218,9 +4241,9 @@ struct constructor_stack
   struct init_node *pending_elts;
   int offset;
   int depth;
-  /* If nonzero, this value should replace the entire
+  /* If value nonzero, this value should replace the entire
      constructor at this level.  */
-  tree replacement_value;
+  struct c_expr replacement_value;
   struct constructor_range_stack *range_stack;
   char constant;
   char simple;
@@ -4399,7 +4422,8 @@ really_start_incremental_init (tree type)
   p->erroneous = constructor_erroneous;
   p->pending_elts = constructor_pending_elts;
   p->depth = constructor_depth;
-  p->replacement_value = 0;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
   p->implicit = 0;
   p->range_stack = 0;
   p->outer = 0;
@@ -4528,7 +4552,8 @@ push_init_level (int implicit)
   p->erroneous = constructor_erroneous;
   p->pending_elts = constructor_pending_elts;
   p->depth = constructor_depth;
-  p->replacement_value = 0;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
   p->implicit = implicit;
   p->outer = 0;
   p->incremental = constructor_incremental;
@@ -4665,18 +4690,23 @@ push_init_level (int implicit)
 }
 
 /* At the end of an implicit or explicit brace level,
-   finish up that level of constructor.
-   If we were outputting the elements as they are read, return 0
+   finish up that level of constructor.  If a single expression
+   with redundant braces initialized that level, return the
+   c_expr structure for that expression.  Otherwise, the original_code
+   element is set to ERROR_MARK.
+   If we were outputting the elements as they are read, return 0 as the value
    from inner levels (process_init_element ignores that),
-   but return error_mark_node from the outermost level
+   but return error_mark_node as the value from the outermost level
    (that's what we want to put in DECL_INITIAL).
-   Otherwise, return a CONSTRUCTOR expression.  */
+   Otherwise, return a CONSTRUCTOR expression as the value.  */
 
-tree
+struct c_expr
 pop_init_level (int implicit)
 {
   struct constructor_stack *p;
-  tree constructor = 0;
+  struct c_expr ret;
+  ret.value = 0;
+  ret.original_code = ERROR_MARK;
 
   if (implicit == 0)
     {
@@ -4748,10 +4778,10 @@ pop_init_level (int implicit)
     }
 
   /* Pad out the end of the structure.  */
-  if (p->replacement_value)
+  if (p->replacement_value.value)
     /* If this closes a superfluous brace pair,
        just pass out the element between them.  */
-    constructor = p->replacement_value;
+    ret = p->replacement_value;
   else if (constructor_type == 0)
     ;
   else if (TREE_CODE (constructor_type) != RECORD_TYPE
@@ -4765,28 +4795,28 @@ pop_init_level (int implicit)
        {
          if (!constructor_erroneous)
            error_init ("empty scalar initializer");
-         constructor = error_mark_node;
+         ret.value = error_mark_node;
        }
       else if (TREE_CHAIN (constructor_elements) != 0)
        {
          error_init ("extra elements in scalar initializer");
-         constructor = TREE_VALUE (constructor_elements);
+         ret.value = TREE_VALUE (constructor_elements);
        }
       else
-       constructor = TREE_VALUE (constructor_elements);
+       ret.value = TREE_VALUE (constructor_elements);
     }
   else
     {
       if (constructor_erroneous)
-       constructor = error_mark_node;
+       ret.value = error_mark_node;
       else
        {
-         constructor = build_constructor (constructor_type,
-                                          nreverse (constructor_elements));
+         ret.value = build_constructor (constructor_type,
+                                        nreverse (constructor_elements));
          if (constructor_constant)
-           TREE_CONSTANT (constructor) = TREE_INVARIANT (constructor) = 1;
+           TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
-           TREE_STATIC (constructor) = 1;
+           TREE_STATIC (ret.value) = 1;
        }
     }
 
@@ -4812,13 +4842,16 @@ pop_init_level (int implicit)
   constructor_stack = p->next;
   free (p);
 
-  if (constructor == 0)
+  if (ret.value == 0)
     {
       if (constructor_stack == 0)
-       return error_mark_node;
-      return NULL_TREE;
+       {
+         ret.value = error_mark_node;
+         return ret;
+       }
+      return ret;
     }
-  return constructor;
+  return ret;
 }
 
 /* Common handling for both array range and field name designators.
@@ -5415,13 +5448,17 @@ find_init_member (tree field)
    Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
    TYPE is the data type that the containing data type wants here.
    FIELD is the field (a FIELD_DECL) or the index that this element fills.
+   If VALUE is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of VALUE, STRICT_STRING is not used.
 
    PENDING if non-nil means output pending elements that belong
    right after this element.  (PENDING is normally 1;
    it is 0 while outputting pending elements, to avoid recursion.)  */
 
 static void
-output_init_element (tree value, tree type, tree field, int pending)
+output_init_element (tree value, bool strict_string, tree type, tree field,
+                    int pending)
 {
   if (type == error_mark_node)
     {
@@ -5477,7 +5514,7 @@ output_init_element (tree value, tree type, tree field, int pending)
                  || TREE_CHAIN (field)))))
     return;
 
-  value = digest_init (type, value, require_constant_value);
+  value = digest_init (type, value, strict_string, require_constant_value);
   if (value == error_mark_node)
     {
       constructor_erroneous = 1;
@@ -5597,7 +5634,7 @@ output_pending_init_elements (int all)
        {
          if (tree_int_cst_equal (elt->purpose,
                                  constructor_unfilled_index))
-           output_init_element (elt->value,
+           output_init_element (elt->value, true,
                                 TREE_TYPE (constructor_type),
                                 constructor_unfilled_index, 0);
          else if (tree_int_cst_lt (constructor_unfilled_index,
@@ -5651,7 +5688,7 @@ output_pending_init_elements (int all)
          if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
            {
              constructor_unfilled_fields = elt->purpose;
-             output_init_element (elt->value, TREE_TYPE (elt->purpose),
+             output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
                                   elt->purpose, 0);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
@@ -5718,10 +5755,11 @@ output_pending_init_elements (int all)
    it calls output_init_element.  */
 
 void
-process_init_element (tree value)
+process_init_element (struct c_expr value)
 {
-  tree orig_value = value;
-  int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
+  tree orig_value = value.value;
+  int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
+  bool strict_string = value.original_code == STRING_CST;
 
   designator_depth = 0;
   designator_errorneous = 0;
@@ -5734,13 +5772,13 @@ process_init_element (tree value)
       && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
       && integer_zerop (constructor_unfilled_index))
     {
-      if (constructor_stack->replacement_value)
+      if (constructor_stack->replacement_value.value)
         error_init ("excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
 
-  if (constructor_stack->replacement_value != 0)
+  if (constructor_stack->replacement_value.value != 0)
     {
       error_init ("excess elements in struct initializer");
       return;
@@ -5773,10 +5811,10 @@ process_init_element (tree value)
     {
       /* If value is a compound literal and we'll be just using its
         content, don't put it into a SAVE_EXPR.  */
-      if (TREE_CODE (value) != COMPOUND_LITERAL_EXPR
+      if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR
          || !require_constant_value
          || flag_isoc99)
-       value = save_expr (value);
+       value.value = save_expr (value.value);
     }
 
   while (1)
@@ -5808,16 +5846,16 @@ process_init_element (tree value)
            }
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && fieldcode == ARRAY_TYPE
              && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
            {
@@ -5825,10 +5863,11 @@ process_init_element (tree value)
              continue;
            }
 
-         if (value)
+         if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value, fieldtype, constructor_fields, 1);
+             output_init_element (value.value, strict_string,
+                                  fieldtype, constructor_fields, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -5890,20 +5929,21 @@ process_init_element (tree value)
             __STDC__ anyway (and we've already complained about the
             member-designator already).  */
          if (warn_traditional && !in_system_header && !constructor_designated
-             && !(value && (integer_zerop (value) || real_zerop (value))))
+             && !(value.value && (integer_zerop (value.value)
+                                  || real_zerop (value.value))))
            warning ("traditional C rejects initialization of unions");
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && fieldcode == ARRAY_TYPE
              && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
            {
@@ -5911,10 +5951,11 @@ process_init_element (tree value)
              continue;
            }
 
-         if (value)
+         if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value, fieldtype, constructor_fields, 1);
+             output_init_element (value.value, strict_string,
+                                  fieldtype, constructor_fields, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -5933,16 +5974,16 @@ process_init_element (tree value)
          enum tree_code eltcode = TREE_CODE (elttype);
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && eltcode == ARRAY_TYPE
              && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE))
            {
@@ -5959,17 +6000,18 @@ process_init_element (tree value)
            }
 
          /* Now output the actual element.  */
-         if (value)
+         if (value.value)
            {
              push_array_bounds (tree_low_cst (constructor_index, 0));
-             output_init_element (value, elttype, constructor_index, 1);
+             output_init_element (value.value, strict_string,
+                                  elttype, constructor_index, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-         if (! value)
+         if (!value.value)
            /* If we are doing the bookkeeping for an element that was
               directly output as a constructor, we must update
               constructor_unfilled_index.  */
@@ -5988,13 +6030,14 @@ process_init_element (tree value)
            }
 
          /* Now output the actual element.  */
-         if (value)
-           output_init_element (value, elttype, constructor_index, 1);
+         if (value.value)
+           output_init_element (value.value, strict_string,
+                                elttype, constructor_index, 1);
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-         if (! value)
+         if (!value.value)
            /* If we are doing the bookkeeping for an element that was
               directly output as a constructor, we must update
               constructor_unfilled_index.  */
@@ -6010,8 +6053,9 @@ process_init_element (tree value)
        }
       else
        {
-         if (value)
-           output_init_element (value, constructor_type, NULL_TREE, 1);
+         if (value.value)
+           output_init_element (value.value, strict_string,
+                                constructor_type, NULL_TREE, 1);
          constructor_fields = 0;
        }
 
index be2734c041bb13fd8ea3fc289467c95a62a29b76..d199ab1228bb394e99772311dd11d3e54a0215a6 100644 (file)
@@ -1,3 +1,8 @@
+2004-07-22  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       PR c/11250
+       * gcc.dg/init-string-1.c: New test.
+
 2004-07-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/15345
diff --git a/gcc/testsuite/gcc.dg/init-string-1.c b/gcc/testsuite/gcc.dg/init-string-1.c
new file mode 100644 (file)
index 0000000..ace3b34
--- /dev/null
@@ -0,0 +1,59 @@
+/* String initializers for arrays must not be parenthesized.  Bug
+   11250 from h.b.furuseth at usit.uio.no.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+#include <stddef.h>
+
+char *a = "a";
+char *b = ("b");
+char *c = (("c"));
+
+char d[] = "d";
+char e[] = ("e"); /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 14 } */
+char f[] = (("f")); /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 16 } */
+
+signed char g[] = { "d" };
+unsigned char h[] = { ("e") }; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 20 } */
+signed char i[] = { (("f")) }; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 22 } */
+
+
+struct s { char a[10]; int b; wchar_t c[10]; };
+
+struct s j = {
+  "j",
+  1,
+  (L"j")
+}; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 32 } */
+struct s k = {
+  (("k")), /* { dg-bogus "warning" "warning in place of error" } */
+  /* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 35 } */
+  1,
+  L"k"
+};
+
+struct s l = {
+  .c = (L"l"), /* { dg-bogus "warning" "warning in place of error" } */
+  /* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 42 } */
+  .a = "l"
+};
+
+struct s m = {
+  .c = L"m",
+  .a = ("m")
+}; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 50 } */
+
+char *n = (char []){ "n" };
+
+char *o = (char []){ ("o") }; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 55 } */
+
+wchar_t *p = (wchar_t [5]){ (L"p") }; /* { dg-bogus "warning" "warning in place of error" } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 58 } */