Author: Sirraide
Date: 2025-04-04T20:54:13+02:00
New Revision: 50f0b30cffa72129a3179bd9ac83692114f6b19f

URL: 
https://github.com/llvm/llvm-project/commit/50f0b30cffa72129a3179bd9ac83692114f6b19f
DIFF: 
https://github.com/llvm/llvm-project/commit/50f0b30cffa72129a3179bd9ac83692114f6b19f.diff

LOG: [Clang] [Sema] Allow static assertions in the first part of a `for` loop 
in C (#134415)

No release note for this one because the one added by #129737 already
mentions ‘non-variable declarations’.

Fixes #56471.

Added: 
    clang/test/SemaCXX/for-static-assert.cpp

Modified: 
    clang/lib/Parse/ParseStmt.cpp
    clang/test/C/C11/n1330.c
    clang/test/Sema/for.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 150b2879fc94f..e8ec140fbe3e5 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2142,7 +2142,13 @@ StmtResult Parser::ParseForStatement(SourceLocation 
*TrailingElseLoc) {
     }
     DeclGroupPtrTy DG;
     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-    if (Tok.is(tok::kw_using)) {
+    if (!getLangOpts().CPlusPlus &&
+        Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
+      ProhibitAttributes(attrs);
+      Decl *D = ParseStaticAssertDeclaration(DeclEnd);
+      DG = Actions.ConvertDeclToDeclGroup(D);
+      FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+    } else if (Tok.is(tok::kw_using)) {
       DG = ParseAliasDeclarationInInitStatement(DeclaratorContext::ForInit,
                                                 attrs);
       FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());

diff  --git a/clang/test/C/C11/n1330.c b/clang/test/C/C11/n1330.c
index 153f1994192dd..f8de2c1557421 100644
--- a/clang/test/C/C11/n1330.c
+++ b/clang/test/C/C11/n1330.c
@@ -43,14 +43,12 @@ void test(void) {
   _Static_assert(1, "this works");
   _Static_assert(0, "this fails"); // expected-error {{static assertion 
failed: this fails}}
 
-  // The use of a _Static_assert in a for loop declaration is prohibited per
-  // 6.8.5p3 requiring the declaration to only declare identifiers for objects
+  // While the use of a _Static_assert in a for loop declaration is prohibited 
per
+  // 6.8.5p3 (requiring the declaration to only declare identifiers for objects
   // having auto or register storage class; a static assertion does not declare
-  // an identifier nor an object.
-  // FIXME: this diagnostic is pretty terrible.
+  // an identifier nor an object), we permit it as an extension.
   int i = 0;
-  for (_Static_assert(1, "this should not compile"); i < 10; ++i) // 
expected-error {{expected identifier or '('}} \
-                                                                     
expected-error {{expected ';' in 'for' statement specifier}}
+  for (_Static_assert(1, "this should compile"); i < 10; ++i)
     ;
 
   // Ensure that only an integer constant expression can be used as the

diff  --git a/clang/test/Sema/for.c b/clang/test/Sema/for.c
index 33aaf7a074ad3..e16169aac0c4c 100644
--- a/clang/test/Sema/for.c
+++ b/clang/test/Sema/for.c
@@ -24,3 +24,8 @@ void b10(void) { for (typedef struct { int i; } (*s)(struct { 
int j; });;); } /*
 void b11 (void) { for (static _Thread_local struct { int i; } s;s.i;); } /* 
c11-warning {{declaration of non-local variable in 'for' loop is a C23 
extension}}
                                                                             
c23-warning {{declaration of non-local variable in 'for' loop is incompatible 
with C standards before C23}} */
 #endif
+
+void b12(void) {
+  for(_Static_assert(1, "");;) {} /* c11-warning {{non-variable declaration in 
'for' loop is a C23 extension}}
+                                     c23-warning {{non-variable declaration in 
'for' loop is incompatible with C standards before C23}} */
+}

diff  --git a/clang/test/SemaCXX/for-static-assert.cpp 
b/clang/test/SemaCXX/for-static-assert.cpp
new file mode 100644
index 0000000000000..f08044324e13b
--- /dev/null
+++ b/clang/test/SemaCXX/for-static-assert.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// C permits a 'static_assert' in the first part of a 'for' loop
+// whereas C++ does not.
+void f() {
+  for(static_assert(true);;) {} // expected-error {{expected expression}}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to