[v9] C, ObjC: Add -Wunterminated-string-initialization

Message ID 20240629125236.12230-1-alx@kernel.org
State New
Headers
Series [v9] C, ObjC: Add -Wunterminated-string-initialization |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Alejandro Colomar June 29, 2024, 12:52 p.m. UTC
  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.

Since Wc++-compat now includes this warning, the test has to be modified
to expect the text of the new warning too, in <gcc.dg/Wcxx-compat-14.c>.

gcc/c-family/ChangeLog:

	* c.opt: Add -Wunterminated-string-initialization.

gcc/c/ChangeLog:

	* c-typeck.cc (digest_init): Separate warnings about character
	  arrays being initialized as unterminated character sequences
	  with string literals, from -Wc++-compat, into a new warning,
	  -Wunterminated-string-initialization.

gcc/ChangeLog:

	* doc/invoke.texi: Document the new
	  -Wunterminated-string-initialization.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wcxx-compat-14.c: Adapt the test to match the new text
	  of the warning, which doesn't say anything about C++ anymore.
	* gcc.dg/Wunterminated-string-initialization.c: New test.

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-ec66160cf413@gmail.com/T/>
Closes: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115185>
Acked-by: Doug McIlroy <douglas.mcilroy@dartmouth.edu>
[Sandra: The documentation parts of the patch are OK.]
Reviewed-by: Sandra Loosemore <sloosemore@baylibre.com>
Reviewed-by: Martin Uecker <uecker@tugraz.at>
Cc: "G. Branden Robinson" <g.branden.robinson@gmail.com>
Cc: Ralph Corderoy <ralph@inputplus.co.uk>
Cc: Dave Kemper <saint.snit@gmail.com>
Cc: Larry McVoy <lm@mcvoy.com>
Cc: Andrew Pinski <pinskia@gmail.com>
Cc: Jonathan Wakely <jwakely.gcc@gmail.com>
Cc: Andrew Clayton <andrew@digital-domain.net>
Cc: David Malcolm <dmalcolm@redhat.com>
Cc: Mike Stump <mikestump@comcast.net>
Cc: Joseph Myers <josmyers@redhat.com>
Cc: Konstantin Kharlamov <Hi-Angel@yandex.ru>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---

Hi!

Here's another round of this patch.

v9 changes:

-  Reviewed by Martin.
-  Add link to related bugzilla bug (and CC its reporter).
-  Rebase on top of git master.

See full range-diff below.

Have a lovely day,
Alex

P.S.: I'm looking for a job; if anyone is interested, please contact me.

Range-diff against v8:
1:  06236d0aa05 ! 1:  1010e7d7ec2 C, ObjC: Add -Wunterminated-string-initialization
    @@ Commit message
         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-ec66160cf413@gmail.com/T/>
    +    Closes: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115185>
         Acked-by: Doug McIlroy <douglas.mcilroy@dartmouth.edu>
         [Sandra: The documentation parts of the patch are OK.]
         Reviewed-by: Sandra Loosemore <sloosemore@baylibre.com>
    +    Reviewed-by: Martin Uecker <uecker@tugraz.at>
         Cc: "G. Branden Robinson" <g.branden.robinson@gmail.com>
         Cc: Ralph Corderoy <ralph@inputplus.co.uk>
         Cc: Dave Kemper <saint.snit@gmail.com>
    @@ Commit message
         Cc: Andrew Pinski <pinskia@gmail.com>
         Cc: Jonathan Wakely <jwakely.gcc@gmail.com>
         Cc: Andrew Clayton <andrew@digital-domain.net>
    -    Cc: Martin Uecker <muecker@gwdg.de>
         Cc: David Malcolm <dmalcolm@redhat.com>
         Cc: Mike Stump <mikestump@comcast.net>
         Cc: Joseph Myers <josmyers@redhat.com>
    +    Cc: Konstantin Kharlamov <Hi-Angel@yandex.ru>
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
      ## gcc/c-family/c.opt ##
    @@ gcc/c/c-typeck.cc: digest_init (location_t init_loc, tree type, tree init, tree
      ## gcc/doc/invoke.texi ##
     @@ gcc/doc/invoke.texi: Objective-C and Objective-C++ Dialects}.
      -Wsystem-headers  -Wtautological-compare  -Wtrampolines  -Wtrigraphs
    - -Wtrivial-auto-var-init -Wtsan -Wtype-limits  -Wundef
    + -Wtrivial-auto-var-init  -Wno-tsan  -Wtype-limits  -Wundef
      -Wuninitialized  -Wunknown-pragmas
     --Wunsuffixed-float-constants  -Wunused
     +-Wunsuffixed-float-constants
    @@ gcc/doc/invoke.texi: Objective-C and Objective-C++ Dialects}.
      -Wunused-const-variable  -Wunused-const-variable=@var{n}
      -Wunused-function  -Wunused-label  -Wunused-local-typedefs
     @@ gcc/doc/invoke.texi: name is still supported, but the newer name is more descriptive.)
    - -Wredundant-move @r{(only for C++)}
    + -Wstring-compare
      -Wtype-limits
      -Wuninitialized
    ++-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
     +-Wunterminated-string-initialization
    - -Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
      -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}
      -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
    + 
     @@ gcc/doc/invoke.texi: arithmetic that may yield out of bounds values. This warning level may
      give a larger number of false positives and is deactivated by default.
      @end table

 gcc/c-family/c.opt                            |  4 ++++
 gcc/c/c-typeck.cc                             |  6 +++---
 gcc/doc/invoke.texi                           | 21 ++++++++++++++++++-
 gcc/testsuite/gcc.dg/Wcxx-compat-14.c         |  2 +-
 .../Wunterminated-string-initialization.c     |  6 ++++++
 5 files changed, 34 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wunterminated-string-initialization.c
  

Comments

Alejandro Colomar June 29, 2024, 12:58 p.m. UTC | #1
On Sat, Jun 29, 2024 at 02:52:40PM GMT, Alejandro Colomar wrote:
> 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.
> 
> Since Wc++-compat now includes this warning, the test has to be modified
> to expect the text of the new warning too, in <gcc.dg/Wcxx-compat-14.c>.
> 
> gcc/c-family/ChangeLog:
> 
> 	* c.opt: Add -Wunterminated-string-initialization.
> 
> gcc/c/ChangeLog:
> 
> 	* c-typeck.cc (digest_init): Separate warnings about character
> 	  arrays being initialized as unterminated character sequences
> 	  with string literals, from -Wc++-compat, into a new warning,
> 	  -Wunterminated-string-initialization.
> 
> gcc/ChangeLog:
> 
> 	* doc/invoke.texi: Document the new
> 	  -Wunterminated-string-initialization.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.dg/Wcxx-compat-14.c: Adapt the test to match the new text
> 	  of the warning, which doesn't say anything about C++ anymore.
> 	* gcc.dg/Wunterminated-string-initialization.c: New test.
> 
> 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-ec66160cf413@gmail.com/T/>
> Closes: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115185>
> Acked-by: Doug McIlroy <douglas.mcilroy@dartmouth.edu>
> [Sandra: The documentation parts of the patch are OK.]
> Reviewed-by: Sandra Loosemore <sloosemore@baylibre.com>
> Reviewed-by: Martin Uecker <uecker@tugraz.at>
> Cc: "G. Branden Robinson" <g.branden.robinson@gmail.com>
> Cc: Ralph Corderoy <ralph@inputplus.co.uk>
> Cc: Dave Kemper <saint.snit@gmail.com>
> Cc: Larry McVoy <lm@mcvoy.com>
> Cc: Andrew Pinski <pinskia@gmail.com>
> Cc: Jonathan Wakely <jwakely.gcc@gmail.com>
> Cc: Andrew Clayton <andrew@digital-domain.net>
> Cc: David Malcolm <dmalcolm@redhat.com>
> Cc: Mike Stump <mikestump@comcast.net>
> Cc: Joseph Myers <josmyers@redhat.com>
> Cc: Konstantin Kharlamov <Hi-Angel@yandex.ru>
> Signed-off-by: Alejandro Colomar <alx@kernel.org>
> ---
> 
> Hi!
> 
> Here's another round of this patch.
> 
> v9 changes:
> 
> -  Reviewed by Martin.
> -  Add link to related bugzilla bug (and CC its reporter).
> -  Rebase on top of git master.
> 
> See full range-diff below.
> 
> Have a lovely day,
> Alex
> 
> P.S.: I'm looking for a job; if anyone is interested, please contact me.
> 
> Range-diff against v8:
> 1:  06236d0aa05 ! 1:  1010e7d7ec2 C, ObjC: Add -Wunterminated-string-initialization
>     @@ Commit message
>          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-ec66160cf413@gmail.com/T/>
>     +    Closes: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115185>
>          Acked-by: Doug McIlroy <douglas.mcilroy@dartmouth.edu>
>          [Sandra: The documentation parts of the patch are OK.]
>          Reviewed-by: Sandra Loosemore <sloosemore@baylibre.com>
>     +    Reviewed-by: Martin Uecker <uecker@tugraz.at>
>          Cc: "G. Branden Robinson" <g.branden.robinson@gmail.com>
>          Cc: Ralph Corderoy <ralph@inputplus.co.uk>
>          Cc: Dave Kemper <saint.snit@gmail.com>
>     @@ Commit message
>          Cc: Andrew Pinski <pinskia@gmail.com>
>          Cc: Jonathan Wakely <jwakely.gcc@gmail.com>
>          Cc: Andrew Clayton <andrew@digital-domain.net>
>     -    Cc: Martin Uecker <muecker@gwdg.de>
>          Cc: David Malcolm <dmalcolm@redhat.com>
>          Cc: Mike Stump <mikestump@comcast.net>
>          Cc: Joseph Myers <josmyers@redhat.com>
>     +    Cc: Konstantin Kharlamov <Hi-Angel@yandex.ru>
>          Signed-off-by: Alejandro Colomar <alx@kernel.org>
>      
>       ## gcc/c-family/c.opt ##
>     @@ gcc/c/c-typeck.cc: digest_init (location_t init_loc, tree type, tree init, tree
>       ## gcc/doc/invoke.texi ##
>      @@ gcc/doc/invoke.texi: Objective-C and Objective-C++ Dialects}.
>       -Wsystem-headers  -Wtautological-compare  -Wtrampolines  -Wtrigraphs
>     - -Wtrivial-auto-var-init -Wtsan -Wtype-limits  -Wundef
>     + -Wtrivial-auto-var-init  -Wno-tsan  -Wtype-limits  -Wundef
>       -Wuninitialized  -Wunknown-pragmas
>      --Wunsuffixed-float-constants  -Wunused
>      +-Wunsuffixed-float-constants
>     @@ gcc/doc/invoke.texi: Objective-C and Objective-C++ Dialects}.
>       -Wunused-const-variable  -Wunused-const-variable=@var{n}
>       -Wunused-function  -Wunused-label  -Wunused-local-typedefs
>      @@ gcc/doc/invoke.texi: name is still supported, but the newer name is more descriptive.)
>     - -Wredundant-move @r{(only for C++)}
>     + -Wstring-compare
>       -Wtype-limits
>       -Wuninitialized
>     ++-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
>      +-Wunterminated-string-initialization
>     - -Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
>       -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}
>       -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
>     + 
>      @@ gcc/doc/invoke.texi: arithmetic that may yield out of bounds values. This warning level may
>       give a larger number of false positives and is deactivated by default.
>       @end table
> 
>  gcc/c-family/c.opt                            |  4 ++++
>  gcc/c/c-typeck.cc                             |  6 +++---
>  gcc/doc/invoke.texi                           | 21 ++++++++++++++++++-
>  gcc/testsuite/gcc.dg/Wcxx-compat-14.c         |  2 +-
>  .../Wunterminated-string-initialization.c     |  6 ++++++
>  5 files changed, 34 insertions(+), 5 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 864ef4e3b3d..c2e43fe13de 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -1464,6 +1464,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 with 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 ffcab7df4d3..efc5c477b3c 100644
> --- a/gcc/c/c-typeck.cc
> +++ b/gcc/c/c-typeck.cc
> @@ -8846,11 +8846,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/doc/invoke.texi b/gcc/doc/invoke.texi
> index 30c4b002d1f..1b6f00b0df5 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -414,7 +414,9 @@ Objective-C and Objective-C++ Dialects}.
>  -Wsystem-headers  -Wtautological-compare  -Wtrampolines  -Wtrigraphs
>  -Wtrivial-auto-var-init  -Wno-tsan  -Wtype-limits  -Wundef
>  -Wuninitialized  -Wunknown-pragmas
> --Wunsuffixed-float-constants  -Wunused
> +-Wunsuffixed-float-constants
> +-Wunterminated-string-initialization
> +-Wunused
>  -Wunused-but-set-parameter  -Wunused-but-set-variable
>  -Wunused-const-variable  -Wunused-const-variable=@var{n}
>  -Wunused-function  -Wunused-label  -Wunused-local-typedefs
> @@ -6450,6 +6452,8 @@ name is still supported, but the newer name is more descriptive.)
>  -Wstring-compare
>  -Wtype-limits
>  -Wuninitialized
> +-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
> +-Wunterminated-string-initialization

Whoops; while in the rebase resolution of conflicts this seemed to
be an addition from elsewhere.  I didn't intend to add it here.  I'll
fix that, and send a v10.  I'll investigate how this line appeared.

>  -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}
>  -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
>  
> @@ -8618,6 +8622,21 @@ arithmetic that may yield out of bounds values. This warning level may
>  give a larger number of false positives and is deactivated by default.
>  @end table
>  
> +@opindex Wunterminated-string-initialization
> +@opindex Wno-unterminated-string-initialization
> +@item -Wunterminated-string-initialization @r{(C and Objective-C only)}
> +Warn about character arrays
> +initialized as unterminated character sequences
> +with a string literal.
> +For example:
> +
> +@smallexample
> +char arr[3] = "foo";
> +@end smallexample
> +
> +This warning is enabled by @option{-Wextra} and @option{-Wc++-compat}.
> +In C++, such initializations are an error.
> +
>  @opindex Warray-compare
>  @opindex Wno-array-compare
>  @item -Warray-compare
> diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-14.c b/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
> index 23783711be6..6df0ee197cc 100644
> --- a/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
> +++ b/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
> @@ -2,5 +2,5 @@
>  /* { dg-options "-Wc++-compat" } */
>  
>  char a1[] = "a";
> -char a2[1] = "a";	/* { dg-warning "C\[+\]\[+\]" } */
> +char a2[1] = "a";	/* { dg-warning "initializer-string for array of 'char' is too long" } */
>  char a3[2] = "a";
> 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..13d5dbc6640
> --- /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 "initializer-string for array of 'char' is too long" } */
> +char a3[2] = "a";
> -- 
> 2.45.2
>
  
Alejandro Colomar June 29, 2024, 1:01 p.m. UTC | #2
On Sat, Jun 29, 2024 at 02:58:48PM GMT, Alejandro Colomar wrote:
> On Sat, Jun 29, 2024 at 02:52:40PM GMT, Alejandro Colomar wrote:
> > @@ -6450,6 +6452,8 @@ name is still supported, but the newer name is more descriptive.)
> >  -Wstring-compare
> >  -Wtype-limits
> >  -Wuninitialized
> > +-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
> > +-Wunterminated-string-initialization
> 
> Whoops; while in the rebase resolution of conflicts this seemed to
> be an addition from elsewhere.  I didn't intend to add it here.  I'll
> fix that, and send a v10.  I'll investigate how this line appeared.

Ahhh; it seems that line had been removed, not added, somewhere between
my v8 and v9.  I misunderstood the git conflict.

> 
> >  -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}
> >  -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
  

Patch

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 864ef4e3b3d..c2e43fe13de 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1464,6 +1464,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 with 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 ffcab7df4d3..efc5c477b3c 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -8846,11 +8846,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/doc/invoke.texi b/gcc/doc/invoke.texi
index 30c4b002d1f..1b6f00b0df5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -414,7 +414,9 @@  Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtautological-compare  -Wtrampolines  -Wtrigraphs
 -Wtrivial-auto-var-init  -Wno-tsan  -Wtype-limits  -Wundef
 -Wuninitialized  -Wunknown-pragmas
--Wunsuffixed-float-constants  -Wunused
+-Wunsuffixed-float-constants
+-Wunterminated-string-initialization
+-Wunused
 -Wunused-but-set-parameter  -Wunused-but-set-variable
 -Wunused-const-variable  -Wunused-const-variable=@var{n}
 -Wunused-function  -Wunused-label  -Wunused-local-typedefs
@@ -6450,6 +6452,8 @@  name is still supported, but the newer name is more descriptive.)
 -Wstring-compare
 -Wtype-limits
 -Wuninitialized
+-Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
+-Wunterminated-string-initialization
 -Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}
 -Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}}
 
@@ -8618,6 +8622,21 @@  arithmetic that may yield out of bounds values. This warning level may
 give a larger number of false positives and is deactivated by default.
 @end table
 
+@opindex Wunterminated-string-initialization
+@opindex Wno-unterminated-string-initialization
+@item -Wunterminated-string-initialization @r{(C and Objective-C only)}
+Warn about character arrays
+initialized as unterminated character sequences
+with a string literal.
+For example:
+
+@smallexample
+char arr[3] = "foo";
+@end smallexample
+
+This warning is enabled by @option{-Wextra} and @option{-Wc++-compat}.
+In C++, such initializations are an error.
+
 @opindex Warray-compare
 @opindex Wno-array-compare
 @item -Warray-compare
diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-14.c b/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
index 23783711be6..6df0ee197cc 100644
--- a/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
+++ b/gcc/testsuite/gcc.dg/Wcxx-compat-14.c
@@ -2,5 +2,5 @@ 
 /* { dg-options "-Wc++-compat" } */
 
 char a1[] = "a";
-char a2[1] = "a";	/* { dg-warning "C\[+\]\[+\]" } */
+char a2[1] = "a";	/* { dg-warning "initializer-string for array of 'char' is too long" } */
 char a3[2] = "a";
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..13d5dbc6640
--- /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 "initializer-string for array of 'char' is too long" } */
+char a3[2] = "a";