diff mbox series

Add -std=c2x, -std=gnu2x, -Wc11-c2x-compat, C2X _Static_assert support

Message ID alpine.DEB.2.21.1810172358520.27972@digraph.polyomino.org.uk
State New
Headers show
Series Add -std=c2x, -std=gnu2x, -Wc11-c2x-compat, C2X _Static_assert support | expand

Commit Message

Joseph Myers Oct. 17, 2018, 11:59 p.m. UTC
Now new features are starting to be added to a C2X draft (in the C2x
branch of the C standard git repository, no public WG14 document yet),
it's time to add -std=c2x and associated options to GCC for use in
enabling C2X features.

This patch adds the expected set of options: -std=c2x, -std=gnu2x,
-Wc11-c2x-compat.  A first C2X feature is added (the only one so far
in the repository that's obviously relevant to GCC): support (as in
C++) for the string constant to be omitted in _Static_assert.  This
feature is duly also supported as an extension in earlier standard
modes (diagnosed with -pedantic, unless -Wno-c11-c2x-compat is given,
or with -Wc11-c2x-compat even in C2X mode).

Bootstrapped with no regressions on x86_64-pc-linux-gnu.  Applied to 
mainline.

gcc/
2018-10-17  Joseph Myers  <joseph@codesourcery.com>

	* doc/cpp.texi (__STDC_VERSION__): Document C2X handling.
	* doc/invoke.texi (-std=c2x, -std=gnu2x): Document new options.
	* doc/standards.texi (C Language): Document C2X.
	* dwarf2out.c (highest_c_language), config/rl78/rl78.c
	(rl78_option_override): Handle "GNU C2X" language name.

gcc/c/
2018-10-17  Joseph Myers  <joseph@codesourcery.com>

	* c-errors.c (pedwarn_c11): New function.
	* c-parser.c (disable_extension_diagnostics): Save
	warn_c11_c2x_compat and set it to 0.
	(restore_extension_diagnostics): Restore warn_c11_c2x_compat.
	(c_parser_static_assert_declaration_no_semi): Handle
	_Static_assert without string constant.
	* c-tree.h (pedwarn_c11): New prototype.

gcc/c-family/
2018-10-17  Joseph Myers  <joseph@codesourcery.com>

	* c-common.c (flag_isoc2x): New variable.
	* c-common.h (clk_c): Update comment to reference C2X.
	(flag_isoc99, flag_isoc11): Update comments to reference future
	standard versions in general.
	(flag_isoc2x): Declare.
	* c-opts.c (set_std_c2x): New function.
	(c_common_handle_option): Handle -std=c2x and -std=gnu2x.
	(set_std_c89, set_std_c99, set_std_c11, set_std_c17): Set
	flag_isoc2x to 0.
	* c.opt (Wc11-c2x-compat, std=c2x, std=gnu2x): New options.

gcc/testsuite/
2018-10-17  Joseph Myers  <joseph@codesourcery.com>

	* gcc.dg/c11-static-assert-7.c, gcc.dg/c11-static-assert-8.c,
	gcc.dg/c11-static-assert-9.c, gcc.dg/c2x-static-assert-1.c,
	gcc.dg/c2x-static-assert-2.c, gcc.dg/c99-static-assert-2.c,
	gcc.dg/gnu2x-static-assert-1.c: New tests.
	* gcc.dg/missing-symbol-3.c: Update expected fix-it text.

libcpp/
2018-10-17  Joseph Myers  <joseph@codesourcery.com>

	* include/cpplib.h (enum c_lang): Add CLK_GNUC2X and CLK_STDC2X.
	* init.c (lang_defaults): Add GNUC2X and STDC2X entries.
	(cpp_init_builtins): Define __STDC_VERSION__ to 202000L for C2X.

Comments

Martin Liška Nov. 23, 2020, 12:07 p.m. UTC | #1
On 10/18/18 1:59 AM, Joseph Myers wrote:
> -		|| strcmp (language_string, "GNU C17") == 0)
> +		|| strcmp (language_string, "GNU C17") == 0
> +		|| strcmp (language_string, "GNU C2X"))

Hello Joseph.

Shouldn't this hunk be '|| strcmp (language_string, "GNU C2X") == 0' ?

Thanks,
Martin
Joseph Myers Nov. 23, 2020, 4:19 p.m. UTC | #2
On Mon, 23 Nov 2020, Martin Liška wrote:

> On 10/18/18 1:59 AM, Joseph Myers wrote:
> > -		|| strcmp (language_string, "GNU C17") == 0)
> > +		|| strcmp (language_string, "GNU C17") == 0
> > +		|| strcmp (language_string, "GNU C2X"))
> 
> Hello Joseph.
> 
> Shouldn't this hunk be '|| strcmp (language_string, "GNU C2X") == 0' ?

Yes.

(There is a question of at what point we decide to assume that C2X will be 
published on the schedule approved by ISO processes and change references 
to refer to C23 and add all the corresponding option names referring to 
C23.)
Martin Liška Nov. 26, 2020, 1:12 p.m. UTC | #3
On 11/23/20 5:19 PM, Joseph Myers wrote:
> On Mon, 23 Nov 2020, Martin Liška wrote:
> 
>> On 10/18/18 1:59 AM, Joseph Myers wrote:
>>> -		|| strcmp (language_string, "GNU C17") == 0)
>>> +		|| strcmp (language_string, "GNU C17") == 0
>>> +		|| strcmp (language_string, "GNU C2X"))
>>
>> Hello Joseph.
>>
>> Shouldn't this hunk be '|| strcmp (language_string, "GNU C2X") == 0' ?
> 
> Yes.

All right, I pushed that as 2a93fa478533908acd4595e6c1dd32885183260c.

Thanks,
Martin

> 
> (There is a question of at what point we decide to assume that C2X will be
> published on the schedule approved by ISO processes and change references
> to refer to C23 and add all the corresponding option names referring to
> C23.)
>
diff mbox series

Patch

Index: gcc/c/c-errors.c
===================================================================
--- gcc/c/c-errors.c	(revision 265250)
+++ gcc/c/c-errors.c	(working copy)
@@ -25,6 +25,45 @@  along with GCC; see the file COPYING3.  If not see
 #include "c-tree.h"
 #include "opts.h"
 
+/* Issue an ISO C11 pedantic warning MSGID if -pedantic outside C2X mode,
+   otherwise issue warning MSGID if -Wc11-c2X-compat is specified.
+   This function is supposed to be used for matters that are allowed in
+   ISO C2X but not supported in ISO C11, thus we explicitly don't pedwarn
+   when C2X is specified.  */
+
+bool
+pedwarn_c11 (location_t location, int opt, const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+  bool warned = false;
+  rich_location richloc (line_table, location);
+
+  va_start (ap, gmsgid);
+  /* If desired, issue the C11/C2X compat warning, which is more specific
+     than -pedantic.  */
+  if (warn_c11_c2x_compat > 0)
+    {
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+			   (pedantic && !flag_isoc2x)
+			   ? DK_PEDWARN : DK_WARNING);
+      diagnostic.option_index = OPT_Wc11_c2x_compat;
+      warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+    }
+  /* -Wno-c11-c2x-compat suppresses even the pedwarns.  */
+  else if (warn_c11_c2x_compat == 0)
+    ;
+  /* For -pedantic outside C2X, issue a pedwarn.  */
+  else if (pedantic && !flag_isoc2x)
+    {
+      diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
+      diagnostic.option_index = opt;
+      warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+    }
+  va_end (ap);
+  return warned;
+}
+
 /* Issue an ISO C99 pedantic warning MSGID if -pedantic outside C11 mode,
    otherwise issue warning MSGID if -Wc99-c11-compat is specified.
    This function is supposed to be used for matters that are allowed in
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 265250)
+++ gcc/c/c-parser.c	(working copy)
@@ -1327,6 +1327,9 @@  disable_extension_diagnostics (void)
 	     /* Similarly for warn_c99_c11_compat.  */
 	     | ((warn_c99_c11_compat == 1) << 9)
 	     | ((warn_c99_c11_compat == -1) << 10)
+	     /* Similarly for warn_c11_c2x_compat.  */
+	     | ((warn_c11_c2x_compat == 1) << 11)
+	     | ((warn_c11_c2x_compat == -1) << 12)
 	     );
   cpp_opts->cpp_pedantic = pedantic = 0;
   warn_pointer_arith = 0;
@@ -1337,6 +1340,7 @@  disable_extension_diagnostics (void)
   warn_overlength_strings = 0;
   warn_c90_c99_compat = 0;
   warn_c99_c11_compat = 0;
+  warn_c11_c2x_compat = 0;
   return ret;
 }
 
@@ -1356,6 +1360,7 @@  restore_extension_diagnostics (int flags)
   /* See above for why is this needed.  */
   warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
   warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
+  warn_c11_c2x_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
 }
 
 /* Helper data structure for parsing #pragma acc routine.  */
@@ -2404,6 +2409,10 @@  c_parser_static_assert_declaration (c_parser *pars
 
    static_assert-declaration-no-semi:
      _Static_assert ( constant-expression , string-literal )
+
+   C2X:
+   static_assert-declaration-no-semi:
+     _Static_assert ( constant-expression )
 */
 
 static void
@@ -2411,7 +2420,7 @@  c_parser_static_assert_declaration_no_semi (c_pars
 {
   location_t assert_loc, value_loc;
   tree value;
-  tree string;
+  tree string = NULL_TREE;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
   assert_loc = c_parser_peek_token (parser)->location;
@@ -2429,27 +2438,33 @@  c_parser_static_assert_declaration_no_semi (c_pars
   value = c_parser_expr_no_commas (parser, NULL).value;
   value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
   parser->lex_untranslated_string = true;
-  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+  if (c_parser_next_token_is (parser, CPP_COMMA))
     {
-      parser->lex_untranslated_string = false;
-      return;
-    }
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_STRING:
-    case CPP_STRING16:
-    case CPP_STRING32:
-    case CPP_WSTRING:
-    case CPP_UTF8STRING:
-      string = c_parser_peek_token (parser)->value;
       c_parser_consume_token (parser);
-      parser->lex_untranslated_string = false;
-      break;
-    default:
-      c_parser_error (parser, "expected string literal");
-      parser->lex_untranslated_string = false;
-      return;
+      switch (c_parser_peek_token (parser)->type)
+	{
+	case CPP_STRING:
+	case CPP_STRING16:
+	case CPP_STRING32:
+	case CPP_WSTRING:
+	case CPP_UTF8STRING:
+	  string = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	  parser->lex_untranslated_string = false;
+	  break;
+	default:
+	  c_parser_error (parser, "expected string literal");
+	  parser->lex_untranslated_string = false;
+	  return;
+	}
     }
+  else if (flag_isoc11)
+    /* If pedantic for pre-C11, the use of _Static_assert itself will
+       have been diagnosed, so do not also diagnose the use of this
+       new C2X feature of _Static_assert.  */
+    pedwarn_c11 (assert_loc, OPT_Wpedantic,
+		 "ISO C11 does not support omitting the string in "
+		 "%<_Static_assert%>");
   parens.require_close (parser);
 
   if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
@@ -2473,7 +2488,12 @@  c_parser_static_assert_declaration_no_semi (c_pars
     }
   constant_expression_warning (value);
   if (integer_zerop (value))
-    error_at (assert_loc, "static assertion failed: %E", string);
+    {
+      if (string)
+	error_at (assert_loc, "static assertion failed: %E", string);
+      else
+	error_at (assert_loc, "static assertion failed");
+    }
 }
 
 /* Parse some declaration specifiers (possibly none) (C90 6.5, C99
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	(revision 265250)
+++ gcc/c/c-tree.h	(working copy)
@@ -762,6 +762,8 @@  extern bool pedwarn_c90 (location_t, int opt, cons
     ATTRIBUTE_GCC_DIAG(3,4);
 extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn_c11 (location_t, int opt, const char *, ...)
+    ATTRIBUTE_GCC_DIAG(3,4);
 
 extern void
 set_c_expr_source_range (c_expr *expr,
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 265250)
+++ gcc/c-family/c-common.c	(working copy)
@@ -214,6 +214,10 @@  int flag_isoc99;
 
 int flag_isoc11;
 
+/* Nonzero means use the ISO C2X dialect of C.  */
+
+int flag_isoc2x;
+
 /* Nonzero means that we have builtin functions, and main is an int.  */
 
 int flag_hosted = 1;
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 265250)
+++ gcc/c-family/c-common.h	(working copy)
@@ -498,7 +498,7 @@  extern GTY(()) tree c_global_trees[CTI_MAX];
 
 enum c_language_kind
 {
-  clk_c		= 0,		/* C90, C94, C99 or C11 */
+  clk_c		= 0,		/* C90, C94, C99, C11 or C2X */
   clk_objc	= 1,		/* clk_c with ObjC features.  */
   clk_cxx	= 2,		/* ANSI/ISO C++ */
   clk_objcxx	= 3		/* clk_cxx with ObjC features.  */
@@ -635,14 +635,18 @@  extern int flag_cond_mismatch;
 
 extern int flag_isoc94;
 
-/* Nonzero means use the ISO C99 (or C11) dialect of C.  */
+/* Nonzero means use the ISO C99 (or later) dialect of C.  */
 
 extern int flag_isoc99;
 
-/* Nonzero means use the ISO C11 dialect of C.  */
+/* Nonzero means use the ISO C11 (or later) dialect of C.  */
 
 extern int flag_isoc11;
 
+/* Nonzero means use the ISO C2X dialect of C.  */
+
+extern int flag_isoc2x;
+
 /* Nonzero means that we have builtin functions, and main is an int.  */
 
 extern int flag_hosted;
Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(revision 265250)
+++ gcc/c-family/c-opts.c	(working copy)
@@ -117,6 +117,7 @@  static void set_std_c89 (int, int);
 static void set_std_c99 (int);
 static void set_std_c11 (int);
 static void set_std_c17 (int);
+static void set_std_c2x (int);
 static void check_deps_environment_vars (void);
 static void handle_deferred_opts (void);
 static void sanitize_cpp_opts (void);
@@ -679,6 +680,16 @@  c_common_handle_option (size_t scode, const char *
 	set_std_c17 (false /* ISO */);
       break;
 
+    case OPT_std_c2x:
+      if (!preprocessing_asm_p)
+	set_std_c2x (true /* ISO */);
+      break;
+
+    case OPT_std_gnu2x:
+      if (!preprocessing_asm_p)
+	set_std_c2x (false /* ISO */);
+      break;
+
     case OPT_trigraphs:
       cpp_opts->trigraphs = 1;
       break;
@@ -1554,6 +1565,7 @@  set_std_c89 (int c94, int iso)
   flag_isoc94 = c94;
   flag_isoc99 = 0;
   flag_isoc11 = 0;
+  flag_isoc2x = 0;
   lang_hooks.name = "GNU C89";
 }
 
@@ -1565,6 +1577,7 @@  set_std_c99 (int iso)
   flag_no_asm = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc2x = 0;
   flag_isoc11 = 0;
   flag_isoc99 = 1;
   flag_isoc94 = 1;
@@ -1579,6 +1592,7 @@  set_std_c11 (int iso)
   flag_no_asm = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc2x = 0;
   flag_isoc11 = 1;
   flag_isoc99 = 1;
   flag_isoc94 = 1;
@@ -1593,6 +1607,7 @@  set_std_c17 (int iso)
   flag_no_asm = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc2x = 0;
   flag_isoc11 = 1;
   flag_isoc99 = 1;
   flag_isoc94 = 1;
@@ -1599,7 +1614,22 @@  set_std_c17 (int iso)
   lang_hooks.name = "GNU C17";
 }
 
+/* Set the C 2X standard (without GNU extensions if ISO).  */
+static void
+set_std_c2x (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_STDC2X: CLK_GNUC2X);
+  flag_no_asm = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  flag_isoc2x = 1;
+  flag_isoc11 = 1;
+  flag_isoc99 = 1;
+  flag_isoc94 = 1;
+  lang_hooks.name = "GNU C2X";
+}
 
+
 /* Set the C++ 98 standard (without GNU extensions if ISO).  */
 static void
 set_std_cxx98 (int iso)
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 265250)
+++ gcc/c-family/c.opt	(working copy)
@@ -366,6 +366,10 @@  Wbuiltin-macro-redefined
 C ObjC C++ ObjC++ CPP(warn_builtin_macro_redefined) CppReason(CPP_W_BUILTIN_MACRO_REDEFINED) Var(cpp_warn_builtin_macro_redefined) Init(1) Warning
 Warn when a built-in preprocessor macro is undefined or redefined.
 
+Wc11-c2x-compat
+C ObjC Var(warn_c11_c2x_compat) Init(-1) Warning
+Warn about features not present in ISO C11, but present in ISO C2X.
+
 Wc90-c99-compat
 C ObjC CPP(cpp_warn_c90_c99_compat) CppReason(CPP_W_C90_C99_COMPAT) Var(warn_c90_c99_compat) Init(-1) Warning
 Warn about features not present in ISO C90, but present in ISO C99.
@@ -1998,6 +2002,10 @@  std=c18
 C ObjC Alias(std=c17)
 Conform to the ISO 2017 C standard (published in 2018).
 
+std=c2x
+C ObjC
+Conform to the ISO 202X C standard draft (experimental and incomplete support).
+
 std=c89
 C ObjC Alias(std=c90)
 Conform to the ISO 1990 C standard.
@@ -2068,6 +2076,10 @@  std=gnu18
 C ObjC Alias(std=gnu17)
 Conform to the ISO 2017 C standard (published in 2018) with GNU extensions.
 
+std=gnu2x
+C ObjC
+Conform to the ISO 202X C standard draft with GNU extensions (experimental and incomplete support).
+
 std=gnu89
 C ObjC Alias(std=gnu90)
 Conform to the ISO 1990 C standard with GNU extensions.
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	(revision 265250)
+++ gcc/config/rl78/rl78.c	(working copy)
@@ -366,6 +366,7 @@  rl78_option_override (void)
       && strcmp (lang_hooks.name, "GNU C")
       && strcmp (lang_hooks.name, "GNU C11")
       && strcmp (lang_hooks.name, "GNU C17")
+      && strcmp (lang_hooks.name, "GNU C2X")
       && strcmp (lang_hooks.name, "GNU C89")
       && strcmp (lang_hooks.name, "GNU C99")
       /* Compiling with -flto results in a language of GNU GIMPLE being used... */
Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 265250)
+++ gcc/doc/cpp.texi	(working copy)
@@ -1887,7 +1887,8 @@  the 1999 revision of the C standard; the value @co
 signifies the 2011 revision of the C standard; the value
 @code{201710L} signifies the 2017 revision of the C standard (which is
 otherwise identical to the 2011 version apart from correction of
-defects).
+defects).  An unspecified value larger than @code{201710L} is used for
+the experimental @option{-std=c2x} and @option{-std=gnu2x} modes.
 
 This macro is not defined if the @option{-traditional-cpp} option is
 used, nor when compiling C++ or Objective-C@.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 265250)
+++ gcc/doc/invoke.texi	(working copy)
@@ -1933,6 +1933,10 @@  same as C11 except for corrections of defects (all
 applied with @option{-std=c11}) and a new value of
 @code{__STDC_VERSION__}, and so is supported to the same extent as C11.
 
+@item c2x
+The next version of the ISO C standard, still under development.  The
+support for this version is experimental and incomplete.
+
 @item gnu90
 @itemx gnu89
 GNU dialect of ISO C90 (including some C99 features).
@@ -1950,6 +1954,11 @@  The name @samp{gnu1x} is deprecated.
 @itemx gnu18
 GNU dialect of ISO C17.  This is the default for C code.
 
+@item gnu2x
+The next version of the ISO C standard, still under development, plus
+GNU extensions.  The support for this version is experimental and
+incomplete.
+
 @item c++98
 @itemx c++03
 The 1998 ISO C++ standard plus the 2003 technical corrigendum and some
Index: gcc/doc/standards.texi
===================================================================
--- gcc/doc/standards.texi	(revision 265250)
+++ gcc/doc/standards.texi	(working copy)
@@ -38,6 +38,8 @@  with some exceptions, and possibly with some exten
 @cindex C1X
 @cindex ISO C17
 @cindex C17
+@cindex ISO C2X
+@cindex C2X
 @cindex Technical Corrigenda
 @cindex TC1
 @cindex Technical Corrigendum 1
@@ -109,6 +111,10 @@  known as @dfn{C17} and is supported with @option{-
 @option{-std=c11}, and the only difference between the options is the
 value of @code{__STDC_VERSION__}.
 
+A further version of the C standard, known as @dfn{C2X}, is under
+development; experimental and incomplete support for this is enabled
+with @option{-std=c2x}.
+
 By default, GCC provides some extensions to the C language that, on
 rare occasions conflict with the C standard.  @xref{C
 Extensions,,Extensions to the C Language Family}.  
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 265250)
+++ gcc/dwarf2out.c	(working copy)
@@ -24329,6 +24329,8 @@  highest_c_language (const char *lang1, const char
   if (strcmp ("GNU C++98", lang1) == 0 || strcmp ("GNU C++98", lang2) == 0)
     return "GNU C++98";
 
+  if (strcmp ("GNU C2X", lang1) == 0 || strcmp ("GNU C2X", lang2) == 0)
+    return "GNU C2X";
   if (strcmp ("GNU C17", lang1) == 0 || strcmp ("GNU C17", lang2) == 0)
     return "GNU C17";
   if (strcmp ("GNU C11", lang1) == 0 || strcmp ("GNU C11", lang2) == 0)
@@ -24408,7 +24410,8 @@  gen_compile_unit_die (const char *filename)
 
 	  if (dwarf_version >= 5 /* || !dwarf_strict */)
 	    if (strcmp (language_string, "GNU C11") == 0
-		|| strcmp (language_string, "GNU C17") == 0)
+		|| strcmp (language_string, "GNU C17") == 0
+		|| strcmp (language_string, "GNU C2X"))
 	      language = DW_LANG_C11;
 	}
     }
Index: gcc/testsuite/gcc.dg/c11-static-assert-7.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-static-assert-7.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c11-static-assert-7.c	(working copy)
@@ -0,0 +1,5 @@ 
+/* Test C11 static assertions.  Omitting the string not supported.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+_Static_assert (1); /* { dg-warning "does not support omitting the string" } */
Index: gcc/testsuite/gcc.dg/c11-static-assert-8.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-static-assert-8.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c11-static-assert-8.c	(working copy)
@@ -0,0 +1,5 @@ 
+/* Test C11 static assertions.  Omitting the string not supported.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Static_assert (1); /* { dg-error "does not support omitting the string" } */
Index: gcc/testsuite/gcc.dg/c11-static-assert-9.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-static-assert-9.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c11-static-assert-9.c	(working copy)
@@ -0,0 +1,6 @@ 
+/* Test C11 static assertions.  Omitting the string not supported, but
+   -Wno-c11-c2x-compat disables the -pedantic diagnostic for that.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic -Wno-c11-c2x-compat" } */
+
+_Static_assert (1);
Index: gcc/testsuite/gcc.dg/c2x-static-assert-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-static-assert-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-static-assert-1.c	(working copy)
@@ -0,0 +1,5 @@ 
+/* Test C2x static assertions.  Omitting the string supported.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic" } */
+
+_Static_assert (1);
Index: gcc/testsuite/gcc.dg/c2x-static-assert-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-static-assert-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-static-assert-2.c	(working copy)
@@ -0,0 +1,6 @@ 
+/* Test C2x static assertions.  Omitting the string supported.  Failed
+   assertions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic" } */
+
+_Static_assert (0); /* { dg-error "static assertion failed" } */
Index: gcc/testsuite/gcc.dg/c99-static-assert-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c99-static-assert-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c99-static-assert-2.c	(working copy)
@@ -0,0 +1,6 @@ 
+/* Test static assertions.  Omitting the string should not result in a
+   duplicate diagnostic in pre-C11 modes.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic" } */
+
+_Static_assert (1); /* { dg-warning "ISO C99 does not support '_Static_assert'" } */
Index: gcc/testsuite/gcc.dg/gnu2x-static-assert-1.c
===================================================================
--- gcc/testsuite/gcc.dg/gnu2x-static-assert-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/gnu2x-static-assert-1.c	(working copy)
@@ -0,0 +1,6 @@ 
+/* Test C11 static assertions.  Omitting the string diagnosed with
+   -Wc11-c2x-compat.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x -Wc11-c2x-compat" } */
+
+_Static_assert (1); /* { dg-warning "does not support omitting the string" } */
Index: gcc/testsuite/gcc.dg/missing-symbol-3.c
===================================================================
--- gcc/testsuite/gcc.dg/missing-symbol-3.c	(revision 265250)
+++ gcc/testsuite/gcc.dg/missing-symbol-3.c	(working copy)
@@ -15,11 +15,11 @@  void test_static_assert_1 (void)
 
 void test_static_assert_2 (void)
 {
-  _Static_assert(sizeof(int) >= sizeof(char); /* { dg-error "expected ',' before ';' token" } */
+  _Static_assert(sizeof(int) >= sizeof(char); /* { dg-error "expected '\\)' before ';' token" } */
   /* { dg-begin-multiline-output "" }
    _Static_assert(sizeof(int) >= sizeof(char);
-                                             ^
-                                             ,
+                 ~                           ^
+                                             )
      { dg-end-multiline-output "" } */
 }
 
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 265250)
+++ libcpp/include/cpplib.h	(working copy)
@@ -167,8 +167,9 @@  enum cpp_ttype
 #undef TK
 
 /* C language kind, used when calling cpp_create_reader.  */
-enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_GNUC11, CLK_GNUC17,
+enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_GNUC11, CLK_GNUC17, CLK_GNUC2X,
 	     CLK_STDC89, CLK_STDC94, CLK_STDC99, CLK_STDC11, CLK_STDC17,
+	     CLK_STDC2X,
 	     CLK_GNUCXX, CLK_CXX98, CLK_GNUCXX11, CLK_CXX11,
 	     CLK_GNUCXX14, CLK_CXX14, CLK_GNUCXX17, CLK_CXX17,
 	     CLK_GNUCXX2A, CLK_CXX2A, CLK_ASM};
Index: libcpp/init.c
===================================================================
--- libcpp/init.c	(revision 265250)
+++ libcpp/init.c	(working copy)
@@ -100,11 +100,13 @@  static const struct lang_flags lang_defaults[] =
   /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1 },
   /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1 },
   /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1 },
   /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0 },
   /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0 },
   /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0 },
   /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0 },
   /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0 },
   /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1 },
   /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0 },
   /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1 },
@@ -521,6 +523,9 @@  cpp_init_builtins (cpp_reader *pfile, int hosted)
     _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
   else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
     _cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
+  else if (CPP_OPTION (pfile, lang) == CLK_STDC2X
+	   || CPP_OPTION (pfile, lang) == CLK_GNUC2X)
+    _cpp_define_builtin (pfile, "__STDC_VERSION__ 202000L");
   else if (CPP_OPTION (pfile, lang) == CLK_STDC17
 	   || CPP_OPTION (pfile, lang) == CLK_GNUC17)
     _cpp_define_builtin (pfile, "__STDC_VERSION__ 201710L");