mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 12:21:09 +08:00
re PR c/11250 (-pedantic accepts `char a[] = ("x");')
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
This commit is contained in:
parent
bf6c40e92d
commit
916c59199c
@ -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
|
||||
|
@ -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
|
||||
;
|
||||
|
||||
|
10
gcc/c-tree.h
10
gcc/c-tree.h
@ -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;
|
||||
|
180
gcc/c-typeck.c
180
gcc/c-typeck.c
@ -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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
59
gcc/testsuite/gcc.dg/init-string-1.c
Normal file
59
gcc/testsuite/gcc.dg/init-string-1.c
Normal file
@ -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 } */
|
Loading…
x
Reference in New Issue
Block a user