Warn about the following: char s[3] = "foo";
Initializing a char array with a string literal of the same length as the size of the array is usually a mistake. Rarely is the case where one wants to create a non-terminated character sequence from a string literal. In some cases, for writing faster code, one may want to use arrays instead of pointers, since that removes the need for storing an array of pointers apart from the strings themselves. char *log_levels[] = { "info", "warning", "err" }; vs. char log_levels[][7] = { "info", "warning", "err" }; This forces the programmer to specify a size, which might change if a new entry is later added. Having no way to enforce null termination is very dangerous, however, so it is useful to have a warning for this, so that the compiler can make sure that the programmer didn't make any mistakes. This warning catches the bug above, so that the programmer will be able to fix it and write: char log_levels[][8] = { "info", "warning", "err" }; This warning already existed as part of -Wc++-compat, but this patch allows enabling it separately. It is also included in -Wextra, since it may not always be desired (when unterminated character sequences are wanted), but it's likely to be desired in most cases. Link: <https://lists.gnu.org/archive/html/groff/2022-11/msg00059.html> Link: <https://lists.gnu.org/archive/html/groff/2022-11/msg00063.html> Link: <https://inbox.sourceware.org/gcc/36da94eb-1cac-5ae8-7fea-ec66160cf...@gmail.com/T/> Acked-by: Doug McIlroy <douglas.mcil...@dartmouth.edu> Cc: "G. Branden Robinson" <g.branden.robin...@gmail.com> Cc: Ralph Corderoy <ra...@inputplus.co.uk> Cc: Dave Kemper <saint.s...@gmail.com> Cc: Larry McVoy <l...@mcvoy.com> Cc: Andrew Pinski <pins...@gmail.com> Cc: Jonathan Wakely <jwakely....@gmail.com> Cc: Andrew Clayton <and...@digital-domain.net> Cc: Martin Uecker <muec...@gwdg.de> Signed-off-by: Alejandro Colomar <a...@kernel.org> --- Hi, I sent v1 to the wrong list. This time I've made sure to write to gcc-patches@. v2 adds some draft of a test, as suggested by Martin. However, I don't know yet how to write those, so the test is just a draft. But I did test the feature, by compiling GCC and compiling some small program with it. Cheers, Alex Range-diff against v1: 1: 61ddf1eb816 ! 1: e40d8f54942 C, ObjC: Add -Wunterminated-string-initialization @@ Commit message Cc: Andrew Pinski <pins...@gmail.com> Cc: Jonathan Wakely <jwakely....@gmail.com> Cc: Andrew Clayton <and...@digital-domain.net> + Cc: Martin Uecker <muec...@gwdg.de> Signed-off-by: Alejandro Colomar <a...@kernel.org> ## gcc/c-family/c.opt ## @@ gcc/c/c-typeck.cc: digest_init (location_t init_loc, tree type, tree init, tree if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) { unsigned HOST_WIDE_INT size + + ## gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c (new) ## +@@ ++/* { dg-do compile } */ ++/* { dg-options "-Wunterminated-string-initialization" } */ ++ ++char a1[] = "a"; ++char a2[1] = "a"; /* { dg-warning "unterminated char sequence" } */ ++char a3[2] = "a"; gcc/c-family/c.opt | 4 ++++ gcc/c/c-typeck.cc | 6 +++--- gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 3333cddeece..7f1fccfe02b 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1382,6 +1382,10 @@ Wunsuffixed-float-constants C ObjC Var(warn_unsuffixed_float_constants) Warning Warn about unsuffixed float constants. +Wunterminated-string-initialization +C ObjC Var(warn_unterminated_string_initialization) Warning LangEnabledBy(C ObjC,Wextra || Wc++-compat) +Warn about character arrays initialized as unterminated character sequences by a string literal. + Wunused C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall) ; documented in common.opt diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 45bacc06c47..ce2750f98bb 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -8420,11 +8420,11 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, pedwarn_init (init_loc, 0, ("initializer-string for array of %qT " "is too long"), typ1); - else if (warn_cxx_compat + else if (warn_unterminated_string_initialization && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) - warning_at (init_loc, OPT_Wc___compat, + warning_at (init_loc, OPT_Wunterminated_string_initialization, ("initializer-string for array of %qT " - "is too long for C++"), typ1); + "is too long"), typ1); if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0) { unsigned HOST_WIDE_INT size diff --git a/gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c b/gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c new file mode 100644 index 00000000000..c6517702d51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-Wunterminated-string-initialization" } */ + +char a1[] = "a"; +char a2[1] = "a"; /* { dg-warning "unterminated char sequence" } */ +char a3[2] = "a"; -- 2.39.2