On 07/30/18 17:49, Joseph Myers wrote: > On Mon, 30 Jul 2018, Bernd Edlinger wrote: > >> Hi, >> >> this is how I would like to handle the over length strings issue in the C FE. >> If the string constant is exactly the right length and ends in one explicit >> NUL character, shorten it by one character. > > I don't think shortening should be limited to that case. I think the case > where the constant is longer than that (and so gets an unconditional > pedwarn) should also have it shortened - any constant that doesn't fit in > the object being initialized should be shortened to fit, whether diagnosed > or not, we should define GENERIC / GIMPLE to disallow too-large string > constants in initializers, and should add an assertion somewhere in the > middle-end that no too-large string constants reach it. >
Okay, there is an update following your suggestion. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
2018-08-01 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-typeck.c (digest_init): Fix overlength strings. diff -pur gcc/c/c-typeck.c gcc/c/c-typeck.c --- gcc/c/c-typeck.c 2018-06-20 18:35:15.000000000 +0200 +++ gcc/c/c-typeck.c 2018-07-31 18:49:50.757586625 +0200 @@ -7435,29 +7435,52 @@ digest_init (location_t init_loc, tree t } } - TREE_TYPE (inside_init) = type; if (TYPE_DOMAIN (type) != NULL_TREE && TYPE_SIZE (type) != NULL_TREE && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init); + unsigned unit = TYPE_PRECISION (typ1) / BITS_PER_UNIT; /* Subtract the size of a single (possibly wide) character because it's ok to ignore the terminating null char that is counted in the length of the constant. */ - if (compare_tree_int (TYPE_SIZE_UNIT (type), - (len - (TYPE_PRECISION (typ1) - / BITS_PER_UNIT))) < 0) - pedwarn_init (init_loc, 0, - ("initializer-string for array of chars " - "is too long")); - else if (warn_cxx_compat - && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) - warning_at (init_loc, OPT_Wc___compat, - ("initializer-string for array chars " - "is too long for C++")); + if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0) + { + pedwarn_init (init_loc, 0, + ("initializer-string for array of chars " + "is too long")); + if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) + { + unsigned HOST_WIDE_INT size + = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + const char *p = TREE_STRING_POINTER (inside_init); + char *q = (char *)xmalloc (size + unit); + + memcpy (q, p, size); + memset (q + size, 0, unit); + inside_init = build_string (size + unit, q); + free (q); + } + } + else if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) + { + if (warn_cxx_compat) + warning_at (init_loc, OPT_Wc___compat, + ("initializer-string for array chars " + "is too long for C++")); + if (len >= 2 * unit) + { + const char *p = TREE_STRING_POINTER (inside_init); + + len -= unit; + if (memcmp (p + len - unit, "\0\0\0\0", unit) == 0) + inside_init = build_string (len, p); + } + } } + TREE_TYPE (inside_init) = type; return inside_init; } else if (INTEGRAL_TYPE_P (typ1))