c-typeck.c (digest_init): Don't allow arrays of signed or unsigned variants of wchar_t to be initialized...

* 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
This commit is contained in:
Joseph Myers 2004-07-25 10:12:21 +01:00 committed by Joseph Myers
parent b785f485ec
commit 197463ae90
4 changed files with 102 additions and 19 deletions

View 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

View 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,

View 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

View File

@ -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" };