public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* c: New C2x keywords
@ 2022-09-06 22:10 Joseph Myers
  2022-09-07  5:41 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: Joseph Myers @ 2022-09-06 22:10 UTC (permalink / raw)
  To: gcc-patches

C2x follows C++ in making alignas, alignof, bool, false,
static_assert, thread_local and true keywords; implement this
accordingly.  This implementation makes them normal keywords in C2x
mode just like any other keyword (C2x leaves open the possibility of
implementation using predefined macros instead - thus, there aren't
any testcases asserting that they aren't macros).  As in C++ and
previous versions of C, true and false are handled like signed 1 and 0
in #if (there was an intermediate state in some C2x drafts where they
had different macro expansions that were unsigned in #if).

Bootstrapped with no regressions for x86_64-pc-linux-gnu.  OK to commit 
(stdalign.h and stdbool.h changes)?

As with the removal of unprototyped functions, this change has a high
risk of breaking some old code and people doing GNU/Linux distribution
builds may wish to see how much is broken in a build with a -std=gnu2x
default.

gcc/
	* ginclude/stdalign.h [defined __STDC_VERSION__ &&
	__STDC_VERSION__ > 201710L]: Disable all content.
	* ginclude/stdbool.h [defined __STDC_VERSION__ && __STDC_VERSION__
	> 201710L] (bool, true, false): Do not define.

gcc/c-family/
	* c-common.cc (c_common_reswords): Use D_C2X instead of D_CXXONLY
	for alignas, alignof, bool, false, static_assert, thread_local and
	true.

gcc/c/
	* c-parser.cc (c_parser_static_assert_declaration_no_semi)
	(c_parser_alignas_specifier, c_parser_alignof_expression): Allow
	for C2x spellings of keywords.
	(c_parser_postfix_expression): Handle RID_TRUE and RID_FALSE.

gcc/testsuite/
	* gcc.dg/c11-keywords-1.c, gcc.dg/c2x-align-1.c,
	gcc.dg/c2x-align-6.c, gcc.dg/c2x-bool-2.c,
	gcc.dg/c2x-static-assert-3.c, gcc.dg/c2x-static-assert-4.c,
	gcc.dg/c2x-thread-local-1.c: New tests.
	* gcc.dg/c2x-bool-1.c: Update expectations.

libcpp/
	* include/cpplib.h (struct cpp_options): Add true_false.
	* expr.cc (eval_token): Check true_false not cplusplus to
	determine whether to handle true and false keywords.
	* init.cc (struct lang_flags): Add true_false.
	(lang_defaults): Update.
	(cpp_set_lang): Set true_false.

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 9746504195b..0a5b7e120c9 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -459,11 +459,11 @@ const struct c_common_resword c_common_reswords[] =
   { "__GIMPLE",		RID_GIMPLE,	D_CONLY },
   { "__PHI",		RID_PHI,	D_CONLY },
   { "__RTL",		RID_RTL,	D_CONLY },
-  { "alignas",		RID_ALIGNAS,	D_CXXONLY | D_CXX11 | D_CXXWARN },
-  { "alignof",		RID_ALIGNOF,	D_CXXONLY | D_CXX11 | D_CXXWARN },
+  { "alignas",		RID_ALIGNAS,	D_C2X | D_CXX11 | D_CXXWARN },
+  { "alignof",		RID_ALIGNOF,	D_C2X | D_CXX11 | D_CXXWARN },
   { "asm",		RID_ASM,	D_ASM },
   { "auto",		RID_AUTO,	0 },
-  { "bool",		RID_BOOL,	D_CXXONLY | D_CXXWARN },
+  { "bool",		RID_BOOL,	D_C2X | D_CXXWARN },
   { "break",		RID_BREAK,	0 },
   { "case",		RID_CASE,	0 },
   { "catch",		RID_CATCH,	D_CXX_OBJC | D_CXXWARN },
@@ -489,7 +489,7 @@ const struct c_common_resword c_common_reswords[] =
   { "explicit",		RID_EXPLICIT,	D_CXXONLY | D_CXXWARN },
   { "export",		RID_EXPORT,	D_CXXONLY | D_CXXWARN },
   { "extern",		RID_EXTERN,	0 },
-  { "false",		RID_FALSE,	D_CXXONLY | D_CXXWARN },
+  { "false",		RID_FALSE,	D_C2X | D_CXXWARN },
   { "float",		RID_FLOAT,	0 },
   { "for",		RID_FOR,	0 },
   { "friend",		RID_FRIEND,	D_CXXONLY | D_CXXWARN },
@@ -515,15 +515,15 @@ const struct c_common_resword c_common_reswords[] =
   { "signed",		RID_SIGNED,	0 },
   { "sizeof",		RID_SIZEOF,	0 },
   { "static",		RID_STATIC,	0 },
-  { "static_assert",    RID_STATIC_ASSERT, D_CXXONLY | D_CXX11 | D_CXXWARN },
+  { "static_assert",    RID_STATIC_ASSERT, D_C2X | D_CXX11 | D_CXXWARN },
   { "static_cast",	RID_STATCAST,	D_CXXONLY | D_CXXWARN },
   { "struct",		RID_STRUCT,	0 },
   { "switch",		RID_SWITCH,	0 },
   { "template",		RID_TEMPLATE,	D_CXXONLY | D_CXXWARN },
   { "this",		RID_THIS,	D_CXXONLY | D_CXXWARN },
-  { "thread_local",	RID_THREAD,	D_CXXONLY | D_CXX11 | D_CXXWARN },
+  { "thread_local",	RID_THREAD,	D_C2X | D_CXX11 | D_CXXWARN },
   { "throw",		RID_THROW,	D_CXX_OBJC | D_CXXWARN },
-  { "true",		RID_TRUE,	D_CXXONLY | D_CXXWARN },
+  { "true",		RID_TRUE,	D_C2X | D_CXXWARN },
   { "try",		RID_TRY,	D_CXX_OBJC | D_CXXWARN },
   { "typedef",		RID_TYPEDEF,	0 },
   { "typename",		RID_TYPENAME,	D_CXXONLY | D_CXXWARN },
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 72db5b527f8..d134448196e 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -2630,13 +2630,14 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
   tree string = NULL_TREE;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+  tree spelling = c_parser_peek_token (parser)->value;
   assert_loc = c_parser_peek_token (parser)->location;
   if (flag_isoc99)
     pedwarn_c99 (assert_loc, OPT_Wpedantic,
-		 "ISO C99 does not support %<_Static_assert%>");
+		 "ISO C99 does not support %qE", spelling);
   else
     pedwarn_c99 (assert_loc, OPT_Wpedantic,
-		 "ISO C90 does not support %<_Static_assert%>");
+		 "ISO C90 does not support %qE", spelling);
   c_parser_consume_token (parser);
   matching_parens parens;
   if (!parens.require_open (parser))
@@ -2667,7 +2668,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
        new C2X feature of _Static_assert.  */
     pedwarn_c11 (assert_loc, OPT_Wpedantic,
 		 "ISO C11 does not support omitting the string in "
-		 "%<_Static_assert%>");
+		 "%qE", spelling);
   parens.require_close (parser);
 
   if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
@@ -3774,13 +3775,14 @@ c_parser_alignas_specifier (c_parser * parser)
   tree ret = error_mark_node;
   location_t loc = c_parser_peek_token (parser)->location;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
+  tree spelling = c_parser_peek_token (parser)->value;
   c_parser_consume_token (parser);
   if (flag_isoc99)
     pedwarn_c99 (loc, OPT_Wpedantic,
-		 "ISO C99 does not support %<_Alignas%>");
+		 "ISO C99 does not support %qE", spelling);
   else
     pedwarn_c99 (loc, OPT_Wpedantic,
-		 "ISO C90 does not support %<_Alignas%>");
+		 "ISO C90 does not support %qE", spelling);
   matching_parens parens;
   if (!parens.require_open (parser))
     return ret;
@@ -8399,10 +8401,12 @@ c_parser_alignof_expression (c_parser *parser)
   location_t end_loc;
   tree alignof_spelling = c_parser_peek_token (parser)->value;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
-  bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling),
-				"_Alignof") == 0;
+  bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
+				"_Alignof") == 0
+			 || strcmp (IDENTIFIER_POINTER (alignof_spelling),
+				    "alignof") == 0);
   /* A diagnostic is not required for the use of this identifier in
-     the implementation namespace; only diagnose it for the C11
+     the implementation namespace; only diagnose it for the C11 or C2X
      spelling because of existing code using the other spellings.  */
   if (is_c11_alignof)
     {
@@ -10272,6 +10276,16 @@ c_parser_postfix_expression (c_parser *parser)
 	  pedwarn_c11 (loc, OPT_Wpedantic,
 		       "ISO C does not support %qs before C2X", "nullptr");
 	  break;
+	case RID_TRUE:
+	  c_parser_consume_token (parser);
+	  expr.value = boolean_true_node;
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
+	case RID_FALSE:
+	  c_parser_consume_token (parser);
+	  expr.value = boolean_false_node;
+	  set_c_expr_source_range (&expr, tok_range);
+	  break;
 	default:
 	  c_parser_error (parser, "expected expression");
 	  expr.set_error ();
diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h
index b10cad1ff24..6ed424343b4 100644
--- a/gcc/ginclude/stdalign.h
+++ b/gcc/ginclude/stdalign.h
@@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #ifndef _STDALIGN_H
 #define _STDALIGN_H
 
-#ifndef __cplusplus
+#if (!defined __cplusplus						\
+     && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L))
 
 #define alignas _Alignas
 #define alignof _Alignof
diff --git a/gcc/ginclude/stdbool.h b/gcc/ginclude/stdbool.h
index fe500d98dad..bcf78395941 100644
--- a/gcc/ginclude/stdbool.h
+++ b/gcc/ginclude/stdbool.h
@@ -30,11 +30,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #ifndef __cplusplus
 
-#define bool	_Bool
 #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
-#define true	((_Bool)+1u)
-#define false	((_Bool)+0u)
+/* bool, true and false are keywords.  */
 #else
+#define bool	_Bool
 #define true	1
 #define false	0
 #endif
diff --git a/gcc/testsuite/gcc.dg/c11-keywords-1.c b/gcc/testsuite/gcc.dg/c11-keywords-1.c
new file mode 100644
index 00000000000..974ccfc75ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-keywords-1.c
@@ -0,0 +1,11 @@
+/* Test new C2x keywords not keywords in C11.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int alignas;
+int alignof;
+int bool;
+int false;
+int true;
+int static_assert;
+int thread_local;
diff --git a/gcc/testsuite/gcc.dg/c2x-align-1.c b/gcc/testsuite/gcc.dg/c2x-align-1.c
new file mode 100644
index 00000000000..25dbd62c550
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-align-1.c
@@ -0,0 +1,41 @@
+/* Test C2x alignment support.  Test valid code.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <stddef.h>
+
+alignas (alignof (max_align_t)) char c;
+extern alignas (max_align_t) char c;
+extern char c;
+
+extern alignas (max_align_t) short s;
+alignas (max_align_t) short s;
+
+alignas (int) int i;
+extern int i;
+
+alignas (max_align_t) long l;
+
+alignas (max_align_t) long long ll;
+
+alignas (max_align_t) float f;
+
+alignas (max_align_t) double d;
+
+alignas (max_align_t) _Complex long double cld;
+
+alignas (0) alignas (int) alignas (char) char ca[10];
+
+alignas ((int) alignof (max_align_t) + 0) int x;
+
+enum e { E = alignof (max_align_t) };
+alignas (E) int y;
+
+void
+func (void)
+{
+  alignas (max_align_t) long long auto_ll;
+}
+
+/* Valid, but useless.  */
+alignas (0) struct s; /* { dg-warning "useless" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-align-6.c b/gcc/testsuite/gcc.dg/c2x-align-6.c
new file mode 100644
index 00000000000..8559a58d96f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-align-6.c
@@ -0,0 +1,8 @@
+/* Test C2x alignof returning minimum alignment for a type.  */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#define _Alignas alignas
+#define _Alignof alignof
+
+#include "c11-align-6.c"
diff --git a/gcc/testsuite/gcc.dg/c2x-bool-1.c b/gcc/testsuite/gcc.dg/c2x-bool-1.c
index b64da1f7b43..992fb318087 100644
--- a/gcc/testsuite/gcc.dg/c2x-bool-1.c
+++ b/gcc/testsuite/gcc.dg/c2x-bool-1.c
@@ -11,16 +11,16 @@ extern void abort (void);
 extern void exit (int);
 extern int strcmp (const char *, const char *);
 
-#if false - 1 < 0
-#error "false signed in #if"
+#if false - 1 >= 0
+#error "false unsigned in #if"
 #endif
 
 #if false != 0
 #error "false not 0 in #if"
 #endif
 
-#if true - 2 < 0
-#error "true signed in #if"
+#if true - 2 >= 0
+#error "true unsigned in #if"
 #endif
 
 #if true != 1
@@ -30,20 +30,14 @@ extern int strcmp (const char *, const char *);
 int
 main (void)
 {
-  if (strcmp (str (bool), "_Bool") != 0)
-    abort ();
   if (_Generic (true, _Bool : 1) != 1)
     abort ();
   if (true != 1)
     abort ();
-  if (strcmp (str (true), "((_Bool)+1u)") != 0)
-    abort ();
   if (_Generic (false, _Bool : 1) != 1)
     abort ();
   if (false != 0)
     abort ();
-  if (strcmp (str (false), "((_Bool)+0u)") != 0)
-    abort ();
   if (strcmp (str (__bool_true_false_are_defined), "1") != 0)
     abort ();
   exit (0);
diff --git a/gcc/testsuite/gcc.dg/c2x-bool-2.c b/gcc/testsuite/gcc.dg/c2x-bool-2.c
new file mode 100644
index 00000000000..4edb34e4de9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-bool-2.c
@@ -0,0 +1,42 @@
+/* Test bool, true and false keywords in C2x.  */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+#if false - 1 >= 0
+#error "false unsigned in #if"
+#endif
+
+#if false != 0
+#error "false not 0 in #if"
+#endif
+
+#if true - 2 >= 0
+#error "true unsigned in #if"
+#endif
+
+#if true != 1
+#error "true not 1 in #if"
+#endif
+
+extern bool b;
+extern _Bool b;
+
+_Static_assert (false == 0);
+_Static_assert (true == 1);
+
+int
+main (void)
+{
+  if (_Generic (true, bool : 1) != 1)
+    abort ();
+  if (true != 1)
+    abort ();
+  if (_Generic (false, bool : 1) != 1)
+    abort ();
+  if (false != 0)
+    abort ();
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-static-assert-3.c b/gcc/testsuite/gcc.dg/c2x-static-assert-3.c
new file mode 100644
index 00000000000..5d84a6a239f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-static-assert-3.c
@@ -0,0 +1,6 @@
+/* Test C2x static assertions.  static_assert keyword.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic" } */
+
+static_assert (1);
+static_assert (1, "message");
diff --git a/gcc/testsuite/gcc.dg/c2x-static-assert-4.c b/gcc/testsuite/gcc.dg/c2x-static-assert-4.c
new file mode 100644
index 00000000000..b3bcfb4ae22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-static-assert-4.c
@@ -0,0 +1,6 @@
+/* Test C2x static assertions.  static_assert keyword.  Failed assertions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic" } */
+
+static_assert (0); /* { dg-error "static assertion failed" } */
+static_assert (0, "message"); /* { dg-error "message" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-thread-local-1.c b/gcc/testsuite/gcc.dg/c2x-thread-local-1.c
new file mode 100644
index 00000000000..e1917bd99dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-thread-local-1.c
@@ -0,0 +1,6 @@
+/* Test C2x thread_local keyword.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+thread_local int a;
+thread_local void f (void); /* { dg-error "storage class" } */
diff --git a/libcpp/expr.cc b/libcpp/expr.cc
index a02290471ae..4bb02c418d0 100644
--- a/libcpp/expr.cc
+++ b/libcpp/expr.cc
@@ -1183,7 +1183,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
     case CPP_NAME:
       if (token->val.node.node == pfile->spec_nodes.n_defined)
 	return parse_defined (pfile);
-      else if (CPP_OPTION (pfile, cplusplus)
+      else if (CPP_OPTION (pfile, true_false)
 	       && (token->val.node.node == pfile->spec_nodes.n_true
 		   || token->val.node.node == pfile->spec_nodes.n_false))
 	{
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 1a3fb19d797..88bec6ca9c2 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -526,6 +526,9 @@ struct cpp_options
   /* Nonzero for C++23 delimited escape sequences.  */
   unsigned char delimited_escape_seqs;
 
+  /* Nonzero for 'true' and 'false' in #if expressions.  */
+  unsigned char true_false;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
diff --git a/libcpp/init.cc b/libcpp/init.cc
index 3e5601a5d96..1e17ea2c69a 100644
--- a/libcpp/init.cc
+++ b/libcpp/init.cc
@@ -98,34 +98,35 @@ struct lang_flags
   char elifdef;
   char warning_directive;
   char delimited_escape_seqs;
+  char true_false;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp szlit elifdef warndir delim */
-  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     1,     0,   1,      1,   1,     1,   0,   1,      1,      0 },
-  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
-  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
-  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
-  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
-  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
-  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     1,     0,   1,      0,   1,     1,   0,   1,      1,      0 },
-  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
-  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
-  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
-  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
-  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
-  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0,   0,      0,      0 },
-  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
-  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
-  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1 },
-  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1 },
-  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0,   0,      0,      0 }
+{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp szlit elifdef warndir delim trufal */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     1,     0,   1,      1,   1,     1,   0,   1,      1,      0,    1 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     1,     0,   1,      0,   1,     1,   0,   1,      1,      0,    1 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0,   0,      0,      0,    1 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
+  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1,    1 },
+  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1,    1 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0,   0,      0,      0,    0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -157,6 +158,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, elifdef)			 = l->elifdef;
   CPP_OPTION (pfile, warning_directive)		 = l->warning_directive;
   CPP_OPTION (pfile, delimited_escape_seqs)	 = l->delimited_escape_seqs;
+  CPP_OPTION (pfile, true_false)		 = l->true_false;
 }
 
 /* Initialize library global state.  */

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: c: New C2x keywords
  2022-09-06 22:10 c: New C2x keywords Joseph Myers
@ 2022-09-07  5:41 ` Richard Biener
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2022-09-07  5:41 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches



> Am 07.09.2022 um 00:11 schrieb Joseph Myers <joseph@codesourcery.com>:
> 
> C2x follows C++ in making alignas, alignof, bool, false,
> static_assert, thread_local and true keywords; implement this
> accordingly.  This implementation makes them normal keywords in C2x
> mode just like any other keyword (C2x leaves open the possibility of
> implementation using predefined macros instead - thus, there aren't
> any testcases asserting that they aren't macros).  As in C++ and
> previous versions of C, true and false are handled like signed 1 and 0
> in #if (there was an intermediate state in some C2x drafts where they
> had different macro expansions that were unsigned in #if).
> 
> Bootstrapped with no regressions for x86_64-pc-linux-gnu.  OK to commit 
> (stdalign.h and stdbool.h changes)?

Ok.

Thanks,
Richard 


> As with the removal of unprototyped functions, this change has a high
> risk of breaking some old code and people doing GNU/Linux distribution
> builds may wish to see how much is broken in a build with a -std=gnu2x
> default.
> 
> gcc/
>    * ginclude/stdalign.h [defined __STDC_VERSION__ &&
>    __STDC_VERSION__ > 201710L]: Disable all content.
>    * ginclude/stdbool.h [defined __STDC_VERSION__ && __STDC_VERSION__
>    > 201710L] (bool, true, false): Do not define.
> 
> gcc/c-family/
>    * c-common.cc (c_common_reswords): Use D_C2X instead of D_CXXONLY
>    for alignas, alignof, bool, false, static_assert, thread_local and
>    true.
> 
> gcc/c/
>    * c-parser.cc (c_parser_static_assert_declaration_no_semi)
>    (c_parser_alignas_specifier, c_parser_alignof_expression): Allow
>    for C2x spellings of keywords.
>    (c_parser_postfix_expression): Handle RID_TRUE and RID_FALSE.
> 
> gcc/testsuite/
>    * gcc.dg/c11-keywords-1.c, gcc.dg/c2x-align-1.c,
>    gcc.dg/c2x-align-6.c, gcc.dg/c2x-bool-2.c,
>    gcc.dg/c2x-static-assert-3.c, gcc.dg/c2x-static-assert-4.c,
>    gcc.dg/c2x-thread-local-1.c: New tests.
>    * gcc.dg/c2x-bool-1.c: Update expectations.
> 
> libcpp/
>    * include/cpplib.h (struct cpp_options): Add true_false.
>    * expr.cc (eval_token): Check true_false not cplusplus to
>    determine whether to handle true and false keywords.
>    * init.cc (struct lang_flags): Add true_false.
>    (lang_defaults): Update.
>    (cpp_set_lang): Set true_false.
> 
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index 9746504195b..0a5b7e120c9 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -459,11 +459,11 @@ const struct c_common_resword c_common_reswords[] =
>   { "__GIMPLE",        RID_GIMPLE,    D_CONLY },
>   { "__PHI",        RID_PHI,    D_CONLY },
>   { "__RTL",        RID_RTL,    D_CONLY },
> -  { "alignas",        RID_ALIGNAS,    D_CXXONLY | D_CXX11 | D_CXXWARN },
> -  { "alignof",        RID_ALIGNOF,    D_CXXONLY | D_CXX11 | D_CXXWARN },
> +  { "alignas",        RID_ALIGNAS,    D_C2X | D_CXX11 | D_CXXWARN },
> +  { "alignof",        RID_ALIGNOF,    D_C2X | D_CXX11 | D_CXXWARN },
>   { "asm",        RID_ASM,    D_ASM },
>   { "auto",        RID_AUTO,    0 },
> -  { "bool",        RID_BOOL,    D_CXXONLY | D_CXXWARN },
> +  { "bool",        RID_BOOL,    D_C2X | D_CXXWARN },
>   { "break",        RID_BREAK,    0 },
>   { "case",        RID_CASE,    0 },
>   { "catch",        RID_CATCH,    D_CXX_OBJC | D_CXXWARN },
> @@ -489,7 +489,7 @@ const struct c_common_resword c_common_reswords[] =
>   { "explicit",        RID_EXPLICIT,    D_CXXONLY | D_CXXWARN },
>   { "export",        RID_EXPORT,    D_CXXONLY | D_CXXWARN },
>   { "extern",        RID_EXTERN,    0 },
> -  { "false",        RID_FALSE,    D_CXXONLY | D_CXXWARN },
> +  { "false",        RID_FALSE,    D_C2X | D_CXXWARN },
>   { "float",        RID_FLOAT,    0 },
>   { "for",        RID_FOR,    0 },
>   { "friend",        RID_FRIEND,    D_CXXONLY | D_CXXWARN },
> @@ -515,15 +515,15 @@ const struct c_common_resword c_common_reswords[] =
>   { "signed",        RID_SIGNED,    0 },
>   { "sizeof",        RID_SIZEOF,    0 },
>   { "static",        RID_STATIC,    0 },
> -  { "static_assert",    RID_STATIC_ASSERT, D_CXXONLY | D_CXX11 | D_CXXWARN },
> +  { "static_assert",    RID_STATIC_ASSERT, D_C2X | D_CXX11 | D_CXXWARN },
>   { "static_cast",    RID_STATCAST,    D_CXXONLY | D_CXXWARN },
>   { "struct",        RID_STRUCT,    0 },
>   { "switch",        RID_SWITCH,    0 },
>   { "template",        RID_TEMPLATE,    D_CXXONLY | D_CXXWARN },
>   { "this",        RID_THIS,    D_CXXONLY | D_CXXWARN },
> -  { "thread_local",    RID_THREAD,    D_CXXONLY | D_CXX11 | D_CXXWARN },
> +  { "thread_local",    RID_THREAD,    D_C2X | D_CXX11 | D_CXXWARN },
>   { "throw",        RID_THROW,    D_CXX_OBJC | D_CXXWARN },
> -  { "true",        RID_TRUE,    D_CXXONLY | D_CXXWARN },
> +  { "true",        RID_TRUE,    D_C2X | D_CXXWARN },
>   { "try",        RID_TRY,    D_CXX_OBJC | D_CXXWARN },
>   { "typedef",        RID_TYPEDEF,    0 },
>   { "typename",        RID_TYPENAME,    D_CXXONLY | D_CXXWARN },
> diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
> index 72db5b527f8..d134448196e 100644
> --- a/gcc/c/c-parser.cc
> +++ b/gcc/c/c-parser.cc
> @@ -2630,13 +2630,14 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
>   tree string = NULL_TREE;
> 
>   gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
> +  tree spelling = c_parser_peek_token (parser)->value;
>   assert_loc = c_parser_peek_token (parser)->location;
>   if (flag_isoc99)
>     pedwarn_c99 (assert_loc, OPT_Wpedantic,
> -         "ISO C99 does not support %<_Static_assert%>");
> +         "ISO C99 does not support %qE", spelling);
>   else
>     pedwarn_c99 (assert_loc, OPT_Wpedantic,
> -         "ISO C90 does not support %<_Static_assert%>");
> +         "ISO C90 does not support %qE", spelling);
>   c_parser_consume_token (parser);
>   matching_parens parens;
>   if (!parens.require_open (parser))
> @@ -2667,7 +2668,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
>        new C2X feature of _Static_assert.  */
>     pedwarn_c11 (assert_loc, OPT_Wpedantic,
>         "ISO C11 does not support omitting the string in "
> -         "%<_Static_assert%>");
> +         "%qE", spelling);
>   parens.require_close (parser);
> 
>   if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
> @@ -3774,13 +3775,14 @@ c_parser_alignas_specifier (c_parser * parser)
>   tree ret = error_mark_node;
>   location_t loc = c_parser_peek_token (parser)->location;
>   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
> +  tree spelling = c_parser_peek_token (parser)->value;
>   c_parser_consume_token (parser);
>   if (flag_isoc99)
>     pedwarn_c99 (loc, OPT_Wpedantic,
> -         "ISO C99 does not support %<_Alignas%>");
> +         "ISO C99 does not support %qE", spelling);
>   else
>     pedwarn_c99 (loc, OPT_Wpedantic,
> -         "ISO C90 does not support %<_Alignas%>");
> +         "ISO C90 does not support %qE", spelling);
>   matching_parens parens;
>   if (!parens.require_open (parser))
>     return ret;
> @@ -8399,10 +8401,12 @@ c_parser_alignof_expression (c_parser *parser)
>   location_t end_loc;
>   tree alignof_spelling = c_parser_peek_token (parser)->value;
>   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
> -  bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling),
> -                "_Alignof") == 0;
> +  bool is_c11_alignof = (strcmp (IDENTIFIER_POINTER (alignof_spelling),
> +                "_Alignof") == 0
> +             || strcmp (IDENTIFIER_POINTER (alignof_spelling),
> +                    "alignof") == 0);
>   /* A diagnostic is not required for the use of this identifier in
> -     the implementation namespace; only diagnose it for the C11
> +     the implementation namespace; only diagnose it for the C11 or C2X
>      spelling because of existing code using the other spellings.  */
>   if (is_c11_alignof)
>     {
> @@ -10272,6 +10276,16 @@ c_parser_postfix_expression (c_parser *parser)
>      pedwarn_c11 (loc, OPT_Wpedantic,
>               "ISO C does not support %qs before C2X", "nullptr");
>      break;
> +    case RID_TRUE:
> +      c_parser_consume_token (parser);
> +      expr.value = boolean_true_node;
> +      set_c_expr_source_range (&expr, tok_range);
> +      break;
> +    case RID_FALSE:
> +      c_parser_consume_token (parser);
> +      expr.value = boolean_false_node;
> +      set_c_expr_source_range (&expr, tok_range);
> +      break;
>    default:
>      c_parser_error (parser, "expected expression");
>      expr.set_error ();
> diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h
> index b10cad1ff24..6ed424343b4 100644
> --- a/gcc/ginclude/stdalign.h
> +++ b/gcc/ginclude/stdalign.h
> @@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> #ifndef _STDALIGN_H
> #define _STDALIGN_H
> 
> -#ifndef __cplusplus
> +#if (!defined __cplusplus                        \
> +     && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L))
> 
> #define alignas _Alignas
> #define alignof _Alignof
> diff --git a/gcc/ginclude/stdbool.h b/gcc/ginclude/stdbool.h
> index fe500d98dad..bcf78395941 100644
> --- a/gcc/ginclude/stdbool.h
> +++ b/gcc/ginclude/stdbool.h
> @@ -30,11 +30,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> 
> #ifndef __cplusplus
> 
> -#define bool    _Bool
> #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
> -#define true    ((_Bool)+1u)
> -#define false    ((_Bool)+0u)
> +/* bool, true and false are keywords.  */
> #else
> +#define bool    _Bool
> #define true    1
> #define false    0
> #endif
> diff --git a/gcc/testsuite/gcc.dg/c11-keywords-1.c b/gcc/testsuite/gcc.dg/c11-keywords-1.c
> new file mode 100644
> index 00000000000..974ccfc75ca
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c11-keywords-1.c
> @@ -0,0 +1,11 @@
> +/* Test new C2x keywords not keywords in C11.  */
> +/* { dg-do compile } */
> +/* { dg-options "-std=c11 -pedantic-errors" } */
> +
> +int alignas;
> +int alignof;
> +int bool;
> +int false;
> +int true;
> +int static_assert;
> +int thread_local;
> diff --git a/gcc/testsuite/gcc.dg/c2x-align-1.c b/gcc/testsuite/gcc.dg/c2x-align-1.c
> new file mode 100644
> index 00000000000..25dbd62c550
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-align-1.c
> @@ -0,0 +1,41 @@
> +/* Test C2x alignment support.  Test valid code.  */
> +/* { dg-do compile } */
> +/* { dg-options "-std=c2x -pedantic-errors" } */
> +
> +#include <stddef.h>
> +
> +alignas (alignof (max_align_t)) char c;
> +extern alignas (max_align_t) char c;
> +extern char c;
> +
> +extern alignas (max_align_t) short s;
> +alignas (max_align_t) short s;
> +
> +alignas (int) int i;
> +extern int i;
> +
> +alignas (max_align_t) long l;
> +
> +alignas (max_align_t) long long ll;
> +
> +alignas (max_align_t) float f;
> +
> +alignas (max_align_t) double d;
> +
> +alignas (max_align_t) _Complex long double cld;
> +
> +alignas (0) alignas (int) alignas (char) char ca[10];
> +
> +alignas ((int) alignof (max_align_t) + 0) int x;
> +
> +enum e { E = alignof (max_align_t) };
> +alignas (E) int y;
> +
> +void
> +func (void)
> +{
> +  alignas (max_align_t) long long auto_ll;
> +}
> +
> +/* Valid, but useless.  */
> +alignas (0) struct s; /* { dg-warning "useless" } */
> diff --git a/gcc/testsuite/gcc.dg/c2x-align-6.c b/gcc/testsuite/gcc.dg/c2x-align-6.c
> new file mode 100644
> index 00000000000..8559a58d96f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-align-6.c
> @@ -0,0 +1,8 @@
> +/* Test C2x alignof returning minimum alignment for a type.  */
> +/* { dg-do run } */
> +/* { dg-options "-std=c2x -pedantic-errors" } */
> +
> +#define _Alignas alignas
> +#define _Alignof alignof
> +
> +#include "c11-align-6.c"
> diff --git a/gcc/testsuite/gcc.dg/c2x-bool-1.c b/gcc/testsuite/gcc.dg/c2x-bool-1.c
> index b64da1f7b43..992fb318087 100644
> --- a/gcc/testsuite/gcc.dg/c2x-bool-1.c
> +++ b/gcc/testsuite/gcc.dg/c2x-bool-1.c
> @@ -11,16 +11,16 @@ extern void abort (void);
> extern void exit (int);
> extern int strcmp (const char *, const char *);
> 
> -#if false - 1 < 0
> -#error "false signed in #if"
> +#if false - 1 >= 0
> +#error "false unsigned in #if"
> #endif
> 
> #if false != 0
> #error "false not 0 in #if"
> #endif
> 
> -#if true - 2 < 0
> -#error "true signed in #if"
> +#if true - 2 >= 0
> +#error "true unsigned in #if"
> #endif
> 
> #if true != 1
> @@ -30,20 +30,14 @@ extern int strcmp (const char *, const char *);
> int
> main (void)
> {
> -  if (strcmp (str (bool), "_Bool") != 0)
> -    abort ();
>   if (_Generic (true, _Bool : 1) != 1)
>     abort ();
>   if (true != 1)
>     abort ();
> -  if (strcmp (str (true), "((_Bool)+1u)") != 0)
> -    abort ();
>   if (_Generic (false, _Bool : 1) != 1)
>     abort ();
>   if (false != 0)
>     abort ();
> -  if (strcmp (str (false), "((_Bool)+0u)") != 0)
> -    abort ();
>   if (strcmp (str (__bool_true_false_are_defined), "1") != 0)
>     abort ();
>   exit (0);
> diff --git a/gcc/testsuite/gcc.dg/c2x-bool-2.c b/gcc/testsuite/gcc.dg/c2x-bool-2.c
> new file mode 100644
> index 00000000000..4edb34e4de9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-bool-2.c
> @@ -0,0 +1,42 @@
> +/* Test bool, true and false keywords in C2x.  */
> +/* { dg-do run } */
> +/* { dg-options "-std=c2x -pedantic-errors" } */
> +
> +extern void abort (void);
> +extern void exit (int);
> +
> +#if false - 1 >= 0
> +#error "false unsigned in #if"
> +#endif
> +
> +#if false != 0
> +#error "false not 0 in #if"
> +#endif
> +
> +#if true - 2 >= 0
> +#error "true unsigned in #if"
> +#endif
> +
> +#if true != 1
> +#error "true not 1 in #if"
> +#endif
> +
> +extern bool b;
> +extern _Bool b;
> +
> +_Static_assert (false == 0);
> +_Static_assert (true == 1);
> +
> +int
> +main (void)
> +{
> +  if (_Generic (true, bool : 1) != 1)
> +    abort ();
> +  if (true != 1)
> +    abort ();
> +  if (_Generic (false, bool : 1) != 1)
> +    abort ();
> +  if (false != 0)
> +    abort ();
> +  exit (0);
> +}
> diff --git a/gcc/testsuite/gcc.dg/c2x-static-assert-3.c b/gcc/testsuite/gcc.dg/c2x-static-assert-3.c
> new file mode 100644
> index 00000000000..5d84a6a239f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-static-assert-3.c
> @@ -0,0 +1,6 @@
> +/* Test C2x static assertions.  static_assert keyword.  */
> +/* { dg-do compile } */
> +/* { dg-options "-std=c2x -pedantic" } */
> +
> +static_assert (1);
> +static_assert (1, "message");
> diff --git a/gcc/testsuite/gcc.dg/c2x-static-assert-4.c b/gcc/testsuite/gcc.dg/c2x-static-assert-4.c
> new file mode 100644
> index 00000000000..b3bcfb4ae22
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-static-assert-4.c
> @@ -0,0 +1,6 @@
> +/* Test C2x static assertions.  static_assert keyword.  Failed assertions.  */
> +/* { dg-do compile } */
> +/* { dg-options "-std=c2x -pedantic" } */
> +
> +static_assert (0); /* { dg-error "static assertion failed" } */
> +static_assert (0, "message"); /* { dg-error "message" } */
> diff --git a/gcc/testsuite/gcc.dg/c2x-thread-local-1.c b/gcc/testsuite/gcc.dg/c2x-thread-local-1.c
> new file mode 100644
> index 00000000000..e1917bd99dc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c2x-thread-local-1.c
> @@ -0,0 +1,6 @@
> +/* Test C2x thread_local keyword.  */
> +/* { dg-do compile } */
> +/* { dg-options "-std=c2x -pedantic-errors" } */
> +
> +thread_local int a;
> +thread_local void f (void); /* { dg-error "storage class" } */
> diff --git a/libcpp/expr.cc b/libcpp/expr.cc
> index a02290471ae..4bb02c418d0 100644
> --- a/libcpp/expr.cc
> +++ b/libcpp/expr.cc
> @@ -1183,7 +1183,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
>     case CPP_NAME:
>       if (token->val.node.node == pfile->spec_nodes.n_defined)
>    return parse_defined (pfile);
> -      else if (CPP_OPTION (pfile, cplusplus)
> +      else if (CPP_OPTION (pfile, true_false)
>           && (token->val.node.node == pfile->spec_nodes.n_true
>           || token->val.node.node == pfile->spec_nodes.n_false))
>    {
> diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
> index 1a3fb19d797..88bec6ca9c2 100644
> --- a/libcpp/include/cpplib.h
> +++ b/libcpp/include/cpplib.h
> @@ -526,6 +526,9 @@ struct cpp_options
>   /* Nonzero for C++23 delimited escape sequences.  */
>   unsigned char delimited_escape_seqs;
> 
> +  /* Nonzero for 'true' and 'false' in #if expressions.  */
> +  unsigned char true_false;
> +
>   /* Holds the name of the target (execution) character set.  */
>   const char *narrow_charset;
> 
> diff --git a/libcpp/init.cc b/libcpp/init.cc
> index 3e5601a5d96..1e17ea2c69a 100644
> --- a/libcpp/init.cc
> +++ b/libcpp/init.cc
> @@ -98,34 +98,35 @@ struct lang_flags
>   char elifdef;
>   char warning_directive;
>   char delimited_escape_seqs;
> +  char true_false;
> };
> 
> static const struct lang_flags lang_defaults[] =
> -{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp szlit elifdef warndir delim */
> -  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     1,     0,   1,      1,   1,     1,   0,   1,      1,      0 },
> -  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
> -  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
> -  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
> -  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
> -  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0 },
> -  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     1,     0,   1,      0,   1,     1,   0,   1,      1,      0 },
> -  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
> -  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
> -  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0,   0,      0,      0 },
> -  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0,   0,      0,      0 },
> -  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
> -  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0,   0,      0,      0 },
> -  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
> -  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0 },
> -  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1 },
> -  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1 },
> -  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0,   0,      0,      0 }
> +{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp szlit elifdef warndir delim trufal */
> +  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
> +  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
> +  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
> +  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    0 },
> +  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     1,     0,   1,      1,   1,     1,   0,   1,      1,      0,    1 },
> +  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
> +  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
> +  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
> +  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
> +  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0,   0,   0,      0,      0,    0 },
> +  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     1,     0,   1,      0,   1,     1,   0,   1,      1,      0,    1 },
> +  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
> +  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
> +  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0,   0,   0,      0,      0,    1 },
> +  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0,   0,   0,      0,      0,    1 },
> +  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   0,   0,      0,      0,    1 },
> +  /* GNUCXX23 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1,    1 },
> +  /* CXX23    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0,   1,   1,      1,      1,    1 },
> +  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0,   0,   0,      0,      0,    0 }
> };
> 
> /* Sets internal flags correctly for a given language.  */
> @@ -157,6 +158,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
>   CPP_OPTION (pfile, elifdef)             = l->elifdef;
>   CPP_OPTION (pfile, warning_directive)         = l->warning_directive;
>   CPP_OPTION (pfile, delimited_escape_seqs)     = l->delimited_escape_seqs;
> +  CPP_OPTION (pfile, true_false)         = l->true_false;
> }
> 
> /* Initialize library global state.  */
> 
> -- 
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-09-07  5:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-06 22:10 c: New C2x keywords Joseph Myers
2022-09-07  5:41 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).