Skip to content

Commit 50f0b30

Browse files
authored
[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.
1 parent e4cbb77 commit 50f0b30

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

clang/lib/Parse/ParseStmt.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -2142,7 +2142,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
21422142
}
21432143
DeclGroupPtrTy DG;
21442144
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2145-
if (Tok.is(tok::kw_using)) {
2145+
if (!getLangOpts().CPlusPlus &&
2146+
Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
2147+
ProhibitAttributes(attrs);
2148+
Decl *D = ParseStaticAssertDeclaration(DeclEnd);
2149+
DG = Actions.ConvertDeclToDeclGroup(D);
2150+
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2151+
} else if (Tok.is(tok::kw_using)) {
21462152
DG = ParseAliasDeclarationInInitStatement(DeclaratorContext::ForInit,
21472153
attrs);
21482154
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());

clang/test/C/C11/n1330.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,12 @@ void test(void) {
4343
_Static_assert(1, "this works");
4444
_Static_assert(0, "this fails"); // expected-error {{static assertion failed: this fails}}
4545

46-
// The use of a _Static_assert in a for loop declaration is prohibited per
47-
// 6.8.5p3 requiring the declaration to only declare identifiers for objects
46+
// While the use of a _Static_assert in a for loop declaration is prohibited per
47+
// 6.8.5p3 (requiring the declaration to only declare identifiers for objects
4848
// having auto or register storage class; a static assertion does not declare
49-
// an identifier nor an object.
50-
// FIXME: this diagnostic is pretty terrible.
49+
// an identifier nor an object), we permit it as an extension.
5150
int i = 0;
52-
for (_Static_assert(1, "this should not compile"); i < 10; ++i) // expected-error {{expected identifier or '('}} \
53-
expected-error {{expected ';' in 'for' statement specifier}}
51+
for (_Static_assert(1, "this should compile"); i < 10; ++i)
5452
;
5553

5654
// Ensure that only an integer constant expression can be used as the

clang/test/Sema/for.c

+5
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } /*
2424
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}}
2525
c23-warning {{declaration of non-local variable in 'for' loop is incompatible with C standards before C23}} */
2626
#endif
27+
28+
void b12(void) {
29+
for(_Static_assert(1, "");;) {} /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}}
30+
c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */
31+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
// C permits a 'static_assert' in the first part of a 'for' loop
4+
// whereas C++ does not.
5+
void f() {
6+
for(static_assert(true);;) {} // expected-error {{expected expression}}
7+
}

0 commit comments

Comments
 (0)