]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Implement C2y static assertions in expressions
authorJoseph Myers <josmyers@redhat.com>
Fri, 24 Oct 2025 00:47:54 +0000 (00:47 +0000)
committerJoseph Myers <josmyers@redhat.com>
Fri, 24 Oct 2025 00:47:54 +0000 (00:47 +0000)
C2y has added support for static assertions as void expressions, in
addition to use as declarations (N3715 was accepted in an online vote
between meetings).

Implement the feature in GCC.  There is a syntactic ambiguity between
a static assertion as a declaration and one as an expression
statement, which the accepted feature resolves by making such a usage
a declaration (this only affects the sequence of syntax productions by
which the code is parsed, not the actual semantics of the assertion);
I've raised the similar ambiguity in for loops on the WG14 reflector.

If just concerned with C2y, and not with diagnosing the use of a
feature not supported in older standard versions, the feature might be
simpler to implement by defaulting to treating static assertions in
ambiguous contexts as expressions rather than declarations, but that
would make it hard to diagnose exactly the cases that are new in C2y
(those depend on the static assertion either not being the whole
expression statement, or being in a context where an expression
statement is allowed but a declaration is not, e.g. the body of an if
statement).  Instead, to support such diagnostics, the implementation
follows the standard in what is considered a declaration and what is
considered an expression, by looking ahead to what follows the closing
parenthesis when a static assertion starts in a context where a
declaration is permitted.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

gcc/c/
* c-parser.cc (c_parser_next_tokens_start_typename)
(c_parser_next_tokens_start_declaration): Add argument for token
to start from
(c_parser_next_tokens_start_declaration): Check for whether static
assertion followed by semicolon.
(c_parser_check_balanced_raw_token_sequence): Declare earlier.
(c_parser_compound_statement_nostart, c_parser_for_statement): Use
c_parser_next_tokens_start_declaration not
c_token_starts_declaration on second token.
(c_parser_unary_expression): Handle static assertions.
* c-parser.h (c_parser_next_tokens_start_declaration): Add
argument.

gcc/testsuite/
* gcc.dg/c23-static-assert-5.c, gcc.dg/c23-static-assert-6.c,
gcc.dg/c23-static-assert-7.c, gcc.dg/c23-static-assert-8.c,
gcc.dg/c2y-static-assert-2.c, gcc.dg/c2y-static-assert-3.c,
gcc.dg/c2y-static-assert-4.c: New tests.

gcc/c/c-parser.cc
gcc/c/c-parser.h
gcc/testsuite/gcc.dg/c23-static-assert-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-static-assert-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-static-assert-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-static-assert-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2y-static-assert-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2y-static-assert-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2y-static-assert-4.c [new file with mode: 0644]

index 56fb0be25b5334fa30a41f9fd2e0e894475fb3a4..0cf3f92a72cbbf99bba849b3169240790c8e1e57 100644 (file)
@@ -675,14 +675,15 @@ c_token_starts_typename (c_token *token)
     }
 }
 
-/* Return true if the next token from PARSER can start a type name,
-   false otherwise.  LA specifies how to do lookahead in order to
+/* Return true if the next token from PARSER, starting from token N, can start
+   a type name, false otherwise.  LA specifies how to do lookahead in order to
    detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
 
 static inline bool
-c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
+c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la,
+                                    unsigned int n = 1)
 {
-  c_token *token = c_parser_peek_token (parser);
+  c_token *token = c_parser_peek_nth_token (parser, n);
   if (c_token_starts_typename (token))
     return true;
 
@@ -695,8 +696,8 @@ c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
       && !parser->objc_could_be_foreach_context
 
       && (la == cla_prefer_type
-         || c_parser_peek_2nd_token (parser)->type == CPP_NAME
-         || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+         || c_parser_peek_nth_token (parser, n + 1)->type == CPP_NAME
+         || c_parser_peek_nth_token (parser, n + 1)->type == CPP_MULT)
 
       /* Only unknown identifiers.  */
       && !lookup_name (token->value))
@@ -892,30 +893,47 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
   return c_token_starts_declspecs (token);
 }
 
-/* Return true if the next tokens from PARSER can start declaration
-   specifiers (not including standard attributes) or a static
-   assertion, false otherwise.  */
+static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
+                                                       unsigned int *);
+
+/* Return true if the next tokens from PARSER (starting with token N, 1-based)
+   can start declaration specifiers (not including standard attributes) or a
+   static assertion, false otherwise.  */
 bool
-c_parser_next_tokens_start_declaration (c_parser *parser)
+c_parser_next_tokens_start_declaration (c_parser *parser, unsigned int n)
 {
-  c_token *token = c_parser_peek_token (parser);
+  c_token *token = c_parser_peek_nth_token (parser, n);
 
   /* Same as above.  */
   if (c_dialect_objc ()
       && token->type == CPP_NAME
       && token->id_kind == C_ID_CLASSNAME
-      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+      && c_parser_peek_nth_token (parser, n + 1)->type == CPP_DOT)
     return false;
 
   /* Labels do not start declarations.  */
   if (token->type == CPP_NAME
-      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+      && c_parser_peek_nth_token (parser, n + 1)->type == CPP_COLON)
     return false;
 
+  /* A static assertion is only a declaration if followed by a semicolon;
+     otherwise, it may be an expression in C2Y.  */
+  if (token->keyword == RID_STATIC_ASSERT
+      && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_PAREN)
+    {
+      n += 2;
+      if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
+         || c_parser_peek_nth_token_raw (parser, n)->type != CPP_CLOSE_PAREN)
+       /* Invalid static assertion syntax; treat as a declaration and report a
+          syntax error there.  */
+       return true;
+      return c_parser_peek_nth_token_raw (parser, n + 1)->type == CPP_SEMICOLON;
+    }
+
   if (c_token_starts_declaration (token))
     return true;
 
-  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
+  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl, n))
     return true;
 
   return false;
@@ -5855,9 +5873,6 @@ c_parser_balanced_token_sequence (c_parser *parser)
     }
 }
 
-static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
-                                                       unsigned int *);
-
 /* Parse arguments of omp::directive or omp::decl attribute.
 
    directive-name ,[opt] clause-list[opt]
@@ -7724,7 +7739,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
          if (!have_std_attrs
-             && (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
+             && (c_parser_next_tokens_start_declaration (parser, 2)
                  || c_parser_nth_token_starts_std_attributes (parser, 2)))
            {
              int ext;
@@ -9132,7 +9147,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
                 && (c_parser_peek_2nd_token (parser)->keyword
                     == RID_EXTENSION))
            c_parser_consume_token (parser);
-         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
+         if (c_parser_next_tokens_start_declaration (parser, 2)
              || c_parser_nth_token_starts_std_attributes (parser, 2))
            {
              int ext;
@@ -10513,8 +10528,9 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
      _Countof ( type-name )
      sizeof unary-expression
      sizeof ( type-name )
+     static-assert-declaration-no-semi
 
-   (_Countof is new in C2y.)
+   (_Countof and the use of static assertions in expressions are new in C2y.)
 
    unary-operator: one of
      & * + - ~ !
@@ -10679,6 +10695,15 @@ c_parser_unary_expression (c_parser *parser)
        case RID_TRANSACTION_RELAXED:
          return c_parser_transaction_expression (parser,
              c_parser_peek_token (parser)->keyword);
+       case RID_STATIC_ASSERT:
+         c_parser_static_assert_declaration_no_semi (parser);
+         pedwarn_c23 (op_loc, OPT_Wpedantic,
+                      "ISO C does not support static assertions in "
+                      "expressions before C2Y");
+         ret.value = void_node;
+         set_c_expr_source_range (&ret, op_loc, op_loc);
+         ret.m_decimal = 0;
+         return ret;
        default:
          return c_parser_postfix_expression (parser);
        }
index a84779bcbf83833158ee7021f898e5e90ec254a9..46713d715ac7ece75b37a552cff53420fad6a926 100644 (file)
@@ -156,7 +156,8 @@ extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
                                       const char *msgid,
                                       location_t = UNKNOWN_LOCATION);
 extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
-bool c_parser_next_tokens_start_declaration (c_parser *parser);
+bool c_parser_next_tokens_start_declaration (c_parser *parser,
+                                            unsigned int n = 1);
 bool c_token_starts_typename (c_token *token);
 
 /* Abstraction to avoid defining c_parser here which messes up gengtype
diff --git a/gcc/testsuite/gcc.dg/c23-static-assert-5.c b/gcc/testsuite/gcc.dg/c23-static-assert-5.c
new file mode 100644 (file)
index 0000000..2edc6b7
--- /dev/null
@@ -0,0 +1,69 @@
+/* Test C2y static assertions in expressions: -pedantic warnings for C23.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8)) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9) /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19)); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8, "message")) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9, "message") /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19, "message")); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c23-static-assert-6.c b/gcc/testsuite/gcc.dg/c23-static-assert-6.c
new file mode 100644 (file)
index 0000000..43e0b27
--- /dev/null
@@ -0,0 +1,70 @@
+/* Test C2y static assertions in expressions: -pedantic-errors errors for
+   C23.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0; /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8)) f (); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9) /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19)); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0; /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8, "message")) f (); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9, "message") /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18, "message"); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19, "message")); /* { dg-error "ISO C does not support static assertions in expressions before C2Y" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c23-static-assert-7.c b/gcc/testsuite/gcc.dg/c23-static-assert-7.c
new file mode 100644 (file)
index 0000000..9c35353
--- /dev/null
@@ -0,0 +1,70 @@
+/* Test C2y static assertions in expressions: -Wc23-c2y-compat warnings for
+   C23.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -Wc23-c2y-compat" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8)) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9) /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19)); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8, "message")) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9, "message") /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19, "message")); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c23-static-assert-8.c b/gcc/testsuite/gcc.dg/c23-static-assert-8.c
new file mode 100644 (file)
index 0000000..118e199
--- /dev/null
@@ -0,0 +1,66 @@
+/* Test C2y static assertions in expressions: not diagnosed for C23 with
+   -pedantic-errors -Wno-c23-c2y-compat.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors -Wno-c23-c2y-compat" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0;
+  extern typeof (static_assert (8)) f ();
+  1 ? static_assert (9) : static_assert (10);
+  if (1)
+    static_assert (11);
+  else
+    static_assert (12);
+  for (;;)
+    static_assert (13);
+  while (true)
+    static_assert (14);
+  do
+    static_assert (15);
+  while (false);
+  switch (16)
+    static_assert (17);
+  (void) static_assert (18);
+  (static_assert (19));
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0;
+  extern typeof (static_assert (8, "message")) f ();
+  1 ? static_assert (9, "message") : static_assert (10, "message");
+  if (1)
+    static_assert (11, "message");
+  else
+    static_assert (12, "message");
+  for (;;)
+    static_assert (13, "message");
+  while (true)
+    static_assert (14, "message");
+  do
+    static_assert (15, "message");
+  while (false);
+  switch (16)
+    static_assert (17, "message");
+  (void) static_assert (18, "message");
+  (static_assert (19, "message"));
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-static-assert-2.c b/gcc/testsuite/gcc.dg/c2y-static-assert-2.c
new file mode 100644 (file)
index 0000000..81cdd9d
--- /dev/null
@@ -0,0 +1,65 @@
+/* Test C2y static assertions in expressions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0;
+  extern typeof (static_assert (8)) f ();
+  1 ? static_assert (9) : static_assert (10);
+  if (1)
+    static_assert (11);
+  else
+    static_assert (12);
+  for (;;)
+    static_assert (13);
+  while (true)
+    static_assert (14);
+  do
+    static_assert (15);
+  while (false);
+  switch (16)
+    static_assert (17);
+  (void) static_assert (18);
+  (static_assert (19));
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0;
+  extern typeof (static_assert (8, "message")) f ();
+  1 ? static_assert (9, "message") : static_assert (10, "message");
+  if (1)
+    static_assert (11, "message");
+  else
+    static_assert (12, "message");
+  for (;;)
+    static_assert (13, "message");
+  while (true)
+    static_assert (14, "message");
+  do
+    static_assert (15, "message");
+  while (false);
+  switch (16)
+    static_assert (17, "message");
+  (void) static_assert (18, "message");
+  (static_assert (19, "message"));
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-static-assert-3.c b/gcc/testsuite/gcc.dg/c2y-static-assert-3.c
new file mode 100644 (file)
index 0000000..fcbf6af
--- /dev/null
@@ -0,0 +1,69 @@
+/* Test C2y static assertions in expressions: -Wc23-c2y-compat warnings.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors -Wc23-c2y-compat" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (1);
+static_assert (2, "message" );
+struct s { int a; static_assert (3); };
+
+void
+f ()
+{
+  static_assert (4);
+ label:
+  static_assert (5);
+  for (static_assert (6);;)
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (7), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8)) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9) /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19)); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (7, "message"), (void) 0; /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  extern typeof (static_assert (8, "message")) f (); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  1
+    ? static_assert (9, "message") /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+    : static_assert (10, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  if (1)
+    static_assert (11, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  else
+    static_assert (12, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  for (;;)
+    static_assert (13, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (true)
+    static_assert (14, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  do
+    static_assert (15, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  while (false);
+  switch (16)
+    static_assert (17, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (void) static_assert (18, "message"); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+  (static_assert (19, "message")); /* { dg-warning "ISO C does not support static assertions in expressions before C2Y" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-static-assert-4.c b/gcc/testsuite/gcc.dg/c2y-static-assert-4.c
new file mode 100644 (file)
index 0000000..87eb7c8
--- /dev/null
@@ -0,0 +1,69 @@
+/* Test C2y static assertions in expressions: failed assertions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+/* Old forms of static assertion still valid.  */
+static_assert (0); /* { dg-error "static assertion failed" } */
+static_assert (0, "message" ); /* { dg-error "static assertion failed" } */
+struct s { int a; static_assert (0); }; /* { dg-error "static assertion failed" } */
+
+void
+f ()
+{
+  static_assert (0); /* { dg-error "static assertion failed" } */
+ label:
+  static_assert (0); /* { dg-error "static assertion failed" } */
+  for (static_assert (0);;) /* { dg-error "static assertion failed" } */
+    ;
+}
+
+/* Test new forms of static assertion.  */
+void
+g ()
+{
+  (void) 0, static_assert (0), (void) 0; /* { dg-error "static assertion failed" } */
+  extern typeof (static_assert (0)) f (); /* { dg-error "static assertion failed" } */
+  1
+    ? static_assert (0) /* { dg-error "static assertion failed" } */
+    : static_assert (0); /* { dg-error "static assertion failed" } */
+  if (1)
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  else
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  for (;;)
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  while (true)
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  do
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  while (false);
+  switch (16)
+    static_assert (0); /* { dg-error "static assertion failed" } */
+  (void) static_assert (0); /* { dg-error "static assertion failed" } */
+  (static_assert (0)); /* { dg-error "static assertion failed" } */
+}
+
+void
+g2 ()
+{
+  (void) 0, static_assert (0, "message"), (void) 0; /* { dg-error "static assertion failed" } */
+  extern typeof (static_assert (0, "message")) f (); /* { dg-error "static assertion failed" } */
+  1
+    ? static_assert (0, "message") /* { dg-error "static assertion failed" } */
+    : static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  if (1)
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  else
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  for (;;)
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  while (true)
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  do
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  while (false);
+  switch (16)
+    static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  (void) static_assert (0, "message"); /* { dg-error "static assertion failed" } */
+  (static_assert (0, "message")); /* { dg-error "static assertion failed" } */
+}