Skip to content

Commit f0605e8

Browse files
committed
[Clang] Allow non-local/non-variable declarations in for loop
1 parent 2af0e2f commit f0605e8

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ Bug Fixes in This Version
237237
when it can affect template argument deduction (#GH122306).
238238
- Fix crash on code completion of function calls involving partial order of function templates
239239
(#GH125500).
240+
- Non-local variable and non-variable declarations in the first clause of a ``for`` loop in C are no longer erroneously
241+
considered an error in C23 mode and are allowed as an extension in earlier language modes.
240242

241243
Bug Fixes to Compiler Builtins
242244
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10794,6 +10794,23 @@ def err_non_local_variable_decl_in_for : Error<
1079410794
"declaration of non-local variable in 'for' loop">;
1079510795
def err_non_variable_decl_in_for : Error<
1079610796
"non-variable declaration in 'for' loop">;
10797+
10798+
def ext_c23_non_local_variable_decl_in_for : Extension<
10799+
"declaration of non-local variable in 'for' loop is a C23 extension">,
10800+
InGroup<C23>;
10801+
10802+
def warn_c17_non_local_variable_decl_in_for : Warning<
10803+
"declaration of non-local variable in 'for' loop is incompatible with C standards before C23">,
10804+
DefaultIgnore, InGroup<CPre23Compat>;
10805+
10806+
def ext_c23_non_variable_decl_in_for : Extension<
10807+
"non-variable declaration in 'for' loop is a C23 extension">,
10808+
InGroup<C23>;
10809+
10810+
def warn_c17_non_variable_decl_in_for : Warning<
10811+
"non-variable declaration in 'for' loop is incompatible with C standards before C23">,
10812+
DefaultIgnore, InGroup<CPre23Compat>;
10813+
1079710814
def err_toomany_element_decls : Error<
1079810815
"only one element declaration is allowed">;
1079910816
def err_selector_element_not_lvalue : Error<

clang/lib/Sema/SemaStmt.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,10 +2269,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
22692269
for (auto *DI : DS->decls()) {
22702270
if (VarDecl *VD = dyn_cast<VarDecl>(DI)) {
22712271
VarDeclSeen = true;
2272-
if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) {
2273-
Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
2274-
DI->setInvalidDecl();
2275-
}
2272+
if (VD->isLocalVarDecl() && !VD->hasLocalStorage())
2273+
Diag(DI->getLocation(),
2274+
getLangOpts().C23
2275+
? diag::warn_c17_non_local_variable_decl_in_for
2276+
: diag::ext_c23_non_local_variable_decl_in_for);
22762277
} else if (!NonVarSeen) {
22772278
// Keep track of the first non-variable declaration we saw so that
22782279
// we can diagnose if we don't see any variable declarations. This
@@ -2284,7 +2285,9 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
22842285
// Diagnose if we saw a non-variable declaration but no variable
22852286
// declarations.
22862287
if (NonVarSeen && !VarDeclSeen)
2287-
Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for);
2288+
Diag(NonVarSeen->getLocation(),
2289+
getLangOpts().C23 ? diag::warn_c17_non_variable_decl_in_for
2290+
: diag::ext_c23_non_variable_decl_in_for);
22882291
}
22892292
}
22902293

clang/test/Sema/for.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify=c11 -std=c11 -pedantic %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 -Wpre-c23-compat %s
23

34
// Check C99 6.8.5p3
45
void b1 (void) { for (void (*f) (void);;); }
5-
void b2 (void) { for (void f (void);;); } // expected-error {{non-variable declaration in 'for' loop}}
6-
void b3 (void) { for (static int f;;); } // expected-error {{declaration of non-local variable}}
7-
void b4 (void) { for (typedef int f;;); } // expected-error {{non-variable declaration in 'for' loop}}
6+
void b2 (void) { for (void f (void);;); } /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}}
7+
c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */
8+
void b3 (void) { for (static int f;;); } /* c11-warning {{declaration of non-local variable in 'for' loop is a C23 extension}}
9+
c23-warning {{declaration of non-local variable in 'for' loop is incompatible with C standards before C23}} */
10+
11+
void b4 (void) { for (typedef int f;;); } /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}}
12+
c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */
813
void b5 (void) { for (struct { int i; } s;;); }
914
void b6 (void) { for (enum { zero, ten = 10 } i;;); }
10-
void b7 (void) { for (struct s { int i; };;); } // expected-error {{non-variable declaration in 'for' loop}}
11-
void b8 (void) { for (static struct { int i; } s;;); } // expected-error {{declaration of non-local variable}}
15+
void b7 (void) { for (struct s { int i; };;); } /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}}
16+
c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */
17+
void b8 (void) { for (static struct { int i; } s;;); } /* c11-warning {{declaration of non-local variable in 'for' loop is a C23 extension}}
18+
c23-warning {{declaration of non-local variable in 'for' loop is incompatible with C standards before C23}} */
1219
void b9 (void) { for (struct { int i; } (*s)(struct { int j; } o) = 0;;); }
13-
void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } // expected-error {{non-variable declaration in 'for' loop}}
20+
void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}}
21+
c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */

0 commit comments

Comments
 (0)