From 17ad43dd4c5dc1a39165a6b2108f4ea793e15eed Mon Sep 17 00:00:00 2001 From: Tom Honermann Date: Thu, 17 Jan 2019 20:43:38 +0000 Subject: [PATCH] Improve the C error for mismatched array string literal initialization. * c-typeck.c (digest_init): Revised the error message produced for ill-formed cases of array initialization with a string literal. (error_init): Make variadic. Co-Authored-By: Jason Merrill From-SVN: r268047 --- gcc/c/ChangeLog | 7 +++ gcc/c/c-typeck.c | 44 +++++++-------- gcc/testsuite/gcc.dg/init-string-2.c | 8 +-- gcc/testsuite/gcc.dg/pr61096-1.c | 6 +-- gcc/testsuite/gcc.dg/utf-array-short-wchar.c | 44 ++++++++------- gcc/testsuite/gcc.dg/utf-array.c | 56 +++++++++++--------- gcc/testsuite/gcc.dg/utf8-2.c | 6 +-- 7 files changed, 91 insertions(+), 80 deletions(-) diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 167c78aeeb3..2accb8fc901 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2019-01-16 Tom Honermann + Jason Merrill + + * c-typeck.c (digest_init): Revised the error message produced for + ill-formed cases of array initialization with a string literal. + (error_init): Make variadic. + 2019-01-12 Jakub Jelinek * c-typeck.c (convert_for_assignment): Fix a comment typo. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 63d177f7a6f..6da1f321835 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -6339,17 +6339,21 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs) GMSGID identifies the message. The component name is taken from the spelling stack. */ -static void -error_init (location_t loc, const char *gmsgid) +static void ATTRIBUTE_GCC_DIAG (2,0) +error_init (location_t loc, const char *gmsgid, ...) { char *ofwhat; auto_diagnostic_group d; /* The gmsgid may be a format string with %< and %>. */ - error_at (loc, gmsgid); + va_list ap; + va_start (ap, gmsgid); + bool warned = emit_diagnostic_valist (DK_ERROR, loc, -1, gmsgid, &ap); + va_end (ap); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); - if (*ofwhat) + if (*ofwhat && warned) inform (loc, "(near initialization for %qs)", ofwhat); } @@ -7722,6 +7726,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, { struct c_expr expr; tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))); + bool incompat_string_cst = false; expr.value = inside_init; expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); expr.original_type = NULL; @@ -7738,27 +7743,18 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, if (char_array) { if (typ2 != char_type_node) - { - error_init (init_loc, "char-array initialized from wide " - "string"); - return error_mark_node; - } - } - else - { - if (typ2 == char_type_node) - { - error_init (init_loc, "wide character array initialized " - "from non-wide string"); - return error_mark_node; - } - else if (!comptypes(typ1, typ2)) - { - error_init (init_loc, "wide character array initialized " - "from incompatible wide string"); - return error_mark_node; - } + incompat_string_cst = true; } + else if (!comptypes (typ1, typ2)) + incompat_string_cst = true; + + if (incompat_string_cst) + { + error_init (init_loc, "cannot initialize array of %qT from " + "a string literal with type array of %qT", + typ1, typ2); + return error_mark_node; + } if (TYPE_DOMAIN (type) != NULL_TREE && TYPE_SIZE (type) != NULL_TREE diff --git a/gcc/testsuite/gcc.dg/init-string-2.c b/gcc/testsuite/gcc.dg/init-string-2.c index 9efd44b3d2f..ded9bf27708 100644 --- a/gcc/testsuite/gcc.dg/init-string-2.c +++ b/gcc/testsuite/gcc.dg/init-string-2.c @@ -28,8 +28,8 @@ 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 a12[] = L"foo"; /* { dg-error "from a string literal with type array of" "a12" } */ +wchar_t a13[] = "foo"; /* { dg-error "from a string literal with type array of .char." "a13" } */ char b0[] = { "foo" }; const signed char b2[4] = { "foo" }; @@ -43,8 +43,8 @@ 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" } */ +char b12[] = { L"foo" }; /* { dg-error "from a string literal with type array of" "b12" } */ +wchar_t b13[] = { "foo" }; /* { dg-error "from a string literal with type array of .char." "b13" } */ struct s { signed char a[10]; int b; ushrt c[10]; }; diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c index 6678d812eb5..111585dd025 100644 --- a/gcc/testsuite/gcc.dg/pr61096-1.c +++ b/gcc/testsuite/gcc.dg/pr61096-1.c @@ -19,9 +19,9 @@ struct g struct f f; /* { dg-warning "invalid use of structure with flexible array member" } */ }; -char w1[] = L"foo"; /* { dg-error "13:char-array initialized from wide string" } */ -__WCHAR_TYPE__ w2[] = "foo"; /* { dg-error "23:wide character array initialized from non-wide string" } */ -__WCHAR_TYPE__ w3[] = U"foo"; /* { dg-error "23:wide character array initialized from incompatible wide string" } */ +char w1[] = L"foo"; /* { dg-error "13:array of .char. from a string literal with type array of" } */ +__WCHAR_TYPE__ w2[] = "foo"; /* { dg-error "23:from a string literal with type array of .char." } */ +__WCHAR_TYPE__ w3[] = U"foo"; /* { dg-error "23:from a string literal with type array of" } */ schar a1[] = "foo"; /* { dg-error "14:array of inappropriate type initialized from string constant" } */ int a2[] = (int[]) { 1 }; /* { dg-warning "12:initializer element is not constant" } */ diff --git a/gcc/testsuite/gcc.dg/utf-array-short-wchar.c b/gcc/testsuite/gcc.dg/utf-array-short-wchar.c index ec478121a07..a582e71178c 100644 --- a/gcc/testsuite/gcc.dg/utf-array-short-wchar.c +++ b/gcc/testsuite/gcc.dg/utf-array-short-wchar.c @@ -10,33 +10,37 @@ typedef __CHAR16_TYPE__ char16_t; typedef __CHAR32_TYPE__ char32_t; const char s_0[] = "ab"; -const char s_1[] = u"ab"; /* { dg-error "from wide string" } */ -const char s_2[] = U"ab"; /* { dg-error "from wide string" } */ -const char s_3[] = L"ab"; /* { dg-error "from wide string" } */ +const char s_1[] = u"ab"; /* { dg-error "from a string literal with type array of" } */ +const char s_2[] = U"ab"; /* { dg-error "from a string literal with type array of" } */ +const char s_3[] = L"ab"; /* { dg-error "from a string literal with type array of" } */ +const char s_4[] = u8"ab"; -const char16_t s16_0[] = "ab"; /* { dg-error "from non-wide" } */ +const char16_t s16_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ const char16_t s16_1[] = u"ab"; -const char16_t s16_2[] = U"ab"; /* { dg-error "from incompatible" } */ +const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type array of" } */ const char16_t s16_3[] = L"ab"; +const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ -const char16_t s16_4[0] = u"ab"; /* { dg-warning "chars is too long" } */ -const char16_t s16_5[1] = u"ab"; /* { dg-warning "chars is too long" } */ -const char16_t s16_6[2] = u"ab"; -const char16_t s16_7[3] = u"ab"; -const char16_t s16_8[4] = u"ab"; +const char16_t s16_5[0] = u"ab"; /* { dg-warning "chars is too long" } */ +const char16_t s16_6[1] = u"ab"; /* { dg-warning "chars is too long" } */ +const char16_t s16_7[2] = u"ab"; +const char16_t s16_8[3] = u"ab"; +const char16_t s16_9[4] = u"ab"; -const char32_t s32_0[] = "ab"; /* { dg-error "from non-wide" } */ -const char32_t s32_1[] = u"ab"; /* { dg-error "from incompatible" } */ +const char32_t s32_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ +const char32_t s32_1[] = u"ab"; /* { dg-error "from a string literal with type array of" } */ const char32_t s32_2[] = U"ab"; -const char32_t s32_3[] = L"ab"; /* { dg-error "from incompatible" } */ +const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of" } */ +const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ -const char32_t s32_4[0] = U"ab"; /* { dg-warning "chars is too long" } */ -const char32_t s32_5[1] = U"ab"; /* { dg-warning "chars is too long" } */ -const char32_t s32_6[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ -const char32_t s32_7[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ -const char32_t s32_8[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ +const char32_t s32_5[0] = U"ab"; /* { dg-warning "chars is too long" } */ +const char32_t s32_6[1] = U"ab"; /* { dg-warning "chars is too long" } */ +const char32_t s32_7[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ +const char32_t s32_8[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ +const char32_t s32_9[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ -const wchar_t sw_0[] = "ab"; /* { dg-error "from non-wide" } */ +const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ const wchar_t sw_1[] = u"ab"; -const wchar_t sw_2[] = U"ab"; /* { dg-error "from incompatible" } */ +const wchar_t sw_2[] = U"ab"; /* { dg-error "from a string literal with type array of" } */ const wchar_t sw_3[] = L"ab"; +const wchar_t sw_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ diff --git a/gcc/testsuite/gcc.dg/utf-array.c b/gcc/testsuite/gcc.dg/utf-array.c index 433ddcfaf48..74a0c0c0e05 100644 --- a/gcc/testsuite/gcc.dg/utf-array.c +++ b/gcc/testsuite/gcc.dg/utf-array.c @@ -10,33 +10,37 @@ typedef __CHAR16_TYPE__ char16_t; typedef __CHAR32_TYPE__ char32_t; const char s_0[] = "ab"; -const char s_1[] = u"ab"; /* { dg-error "from wide string" } */ -const char s_2[] = U"ab"; /* { dg-error "from wide string" } */ -const char s_3[] = L"ab"; /* { dg-error "from wide string" } */ +const char s_1[] = u"ab"; /* { dg-error "from a string literal with type array of" } */ +const char s_2[] = U"ab"; /* { dg-error "from a string literal with type array of" } */ +const char s_3[] = L"ab"; /* { dg-error "from a string literal with type array of .int." } */ +const char s_4[] = u8"ab"; -const char16_t s16_0[] = "ab"; /* { dg-error "from non-wide" } */ +const char16_t s16_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ const char16_t s16_1[] = u"ab"; -const char16_t s16_2[] = U"ab"; /* { dg-error "from incompatible" } */ -const char16_t s16_3[] = L"ab"; /* { dg-error "from incompatible" "" { target { ! wchar_t_char16_t_compatible } } } */ - -const char16_t s16_4[0] = u"ab"; /* { dg-warning "chars is too long" } */ -const char16_t s16_5[1] = u"ab"; /* { dg-warning "chars is too long" } */ -const char16_t s16_6[2] = u"ab"; -const char16_t s16_7[3] = u"ab"; -const char16_t s16_8[4] = u"ab"; - -const char32_t s32_0[] = "ab"; /* { dg-error "from non-wide" } */ -const char32_t s32_1[] = u"ab"; /* { dg-error "from incompatible" } */ +const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type array of" } */ +const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .int." "" { target { ! wchar_t_char16_t_compatible } } } */ +const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ + +const char16_t s16_5[0] = u"ab"; /* { dg-warning "chars is too long" } */ +const char16_t s16_6[1] = u"ab"; /* { dg-warning "chars is too long" } */ +const char16_t s16_7[2] = u"ab"; +const char16_t s16_8[3] = u"ab"; +const char16_t s16_9[4] = u"ab"; + +const char32_t s32_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ +const char32_t s32_1[] = u"ab"; /* { dg-error "from a string literal with type array of" } */ const char32_t s32_2[] = U"ab"; -const char32_t s32_3[] = L"ab"; /* { dg-error "from incompatible" "" { target { ! wchar_t_char32_t_compatible } } } */ - -const char32_t s32_4[0] = U"ab"; /* { dg-warning "chars is too long" } */ -const char32_t s32_5[1] = U"ab"; /* { dg-warning "chars is too long" } */ -const char32_t s32_6[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ -const char32_t s32_7[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ -const char32_t s32_8[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ - -const wchar_t sw_0[] = "ab"; /* { dg-error "from non-wide" } */ -const wchar_t sw_1[] = u"ab"; /* { dg-error "from incompatible" "" { target { ! wchar_t_char16_t_compatible } } } */ -const wchar_t sw_2[] = U"ab"; /* { dg-error "from incompatible" "" { target { ! wchar_t_char32_t_compatible } } } */ +const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .int." "" { target { ! wchar_t_char32_t_compatible } } } */ +const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ + +const char32_t s32_5[0] = U"ab"; /* { dg-warning "chars is too long" } */ +const char32_t s32_6[1] = U"ab"; /* { dg-warning "chars is too long" } */ +const char32_t s32_7[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ +const char32_t s32_8[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ +const char32_t s32_9[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */ + +const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */ +const wchar_t sw_1[] = u"ab"; /* { dg-error "from a string literal with type array of" "" { target { ! wchar_t_char16_t_compatible } } } */ +const wchar_t sw_2[] = U"ab"; /* { dg-error "from a string literal with type array of" "" { target { ! wchar_t_char32_t_compatible } } } */ const wchar_t sw_3[] = L"ab"; +const wchar_t sw_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ diff --git a/gcc/testsuite/gcc.dg/utf8-2.c b/gcc/testsuite/gcc.dg/utf8-2.c index f3b83fe3341..d96b15dccb7 100644 --- a/gcc/testsuite/gcc.dg/utf8-2.c +++ b/gcc/testsuite/gcc.dg/utf8-2.c @@ -8,9 +8,9 @@ typedef __CHAR16_TYPE__ char16_t; typedef __CHAR32_TYPE__ char32_t; const char s0[] = u8"ab"; -const char16_t s1[] = u8"ab"; /* { dg-error "from non-wide" } */ -const char32_t s2[] = u8"ab"; /* { dg-error "from non-wide" } */ -const wchar_t s3[] = u8"ab"; /* { dg-error "from non-wide" } */ +const char16_t s1[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ +const char32_t s2[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ +const wchar_t s3[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */ const char t0[0] = u8"ab"; /* { dg-warning "chars is too long" } */ const char t1[1] = u8"ab"; /* { dg-warning "chars is too long" } */ -- 2.30.2