[clang] 5b3ba26 - [Clang] [Sema] Allow non-local/non-variable declarations in for loop (#129737)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 5 17:03:25 PST 2025
Author: Sirraide
Date: 2025-03-06T02:03:22+01:00
New Revision: 5b3ba261c49bee35debdd54e23a6a181126f798e
URL: https://github.com/llvm/llvm-project/commit/5b3ba261c49bee35debdd54e23a6a181126f798e
DIFF: https://github.com/llvm/llvm-project/commit/5b3ba261c49bee35debdd54e23a6a181126f798e.diff
LOG: [Clang] [Sema] Allow non-local/non-variable declarations in for loop (#129737)
Currently, we error on non-variable or non-local variable declarations
in `for` loops such as `for (struct S {}; 0; ) {}`. However, this is
valid in C23, so this patch changes the error to a compatibilty warning
and also allows this as an extension in earlier language modes. This
also matches GCC’s behaviour.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaStmt.cpp
clang/test/Sema/for.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 32db3fe5740ed..629149bf459b1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -248,6 +248,8 @@ Bug Fixes in This Version
(#GH125500).
- Fixed clang crash when #embed data does not fit into an array
(#GH128987).
+- Non-local variable and non-variable declarations in the first clause of a ``for`` loop in C are no longer incorrectly
+ considered an error in C23 mode and are allowed as an extension in earlier language modes.
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0b121c04cd3c0..ed2da2b355e11 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10797,6 +10797,23 @@ def err_non_local_variable_decl_in_for : Error<
"declaration of non-local variable in 'for' loop">;
def err_non_variable_decl_in_for : Error<
"non-variable declaration in 'for' loop">;
+
+def ext_c23_non_local_variable_decl_in_for : Extension<
+ "declaration of non-local variable in 'for' loop is a C23 extension">,
+ InGroup<C23>;
+
+def warn_c17_non_local_variable_decl_in_for : Warning<
+ "declaration of non-local variable in 'for' loop is incompatible with C standards before C23">,
+ DefaultIgnore, InGroup<CPre23Compat>;
+
+def ext_c23_non_variable_decl_in_for : Extension<
+ "non-variable declaration in 'for' loop is a C23 extension">,
+ InGroup<C23>;
+
+def warn_c17_non_variable_decl_in_for : Warning<
+ "non-variable declaration in 'for' loop is incompatible with C standards before C23">,
+ DefaultIgnore, InGroup<CPre23Compat>;
+
def err_toomany_element_decls : Error<
"only one element declaration is allowed">;
def err_selector_element_not_lvalue : Error<
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index d0b713f074c33..0a193b5299bcc 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2269,10 +2269,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
for (auto *DI : DS->decls()) {
if (VarDecl *VD = dyn_cast<VarDecl>(DI)) {
VarDeclSeen = true;
- if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) {
- Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
- DI->setInvalidDecl();
- }
+ if (VD->isLocalVarDecl() && !VD->hasLocalStorage())
+ Diag(DI->getLocation(),
+ getLangOpts().C23
+ ? diag::warn_c17_non_local_variable_decl_in_for
+ : diag::ext_c23_non_local_variable_decl_in_for);
} else if (!NonVarSeen) {
// Keep track of the first non-variable declaration we saw so that
// we can diagnose if we don't see any variable declarations. This
@@ -2284,7 +2285,9 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
// Diagnose if we saw a non-variable declaration but no variable
// declarations.
if (NonVarSeen && !VarDeclSeen)
- Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for);
+ Diag(NonVarSeen->getLocation(),
+ getLangOpts().C23 ? diag::warn_c17_non_variable_decl_in_for
+ : diag::ext_c23_non_variable_decl_in_for);
}
}
diff --git a/clang/test/Sema/for.c b/clang/test/Sema/for.c
index d0c2f7f21a960..c21ef62247037 100644
--- a/clang/test/Sema/for.c
+++ b/clang/test/Sema/for.c
@@ -1,13 +1,21 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c11 -std=c11 -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 -Wpre-c23-compat %s
// Check C99 6.8.5p3
void b1 (void) { for (void (*f) (void);;); }
-void b2 (void) { for (void f (void);;); } // expected-error {{non-variable declaration in 'for' loop}}
-void b3 (void) { for (static int f;;); } // expected-error {{declaration of non-local variable}}
-void b4 (void) { for (typedef int f;;); } // expected-error {{non-variable declaration in 'for' loop}}
+void b2 (void) { for (void f (void);;); } /* 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}} */
+void b3 (void) { for (static int f;;); } /* 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}} */
+
+void b4 (void) { for (typedef int f;;); } /* 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}} */
void b5 (void) { for (struct { int i; } s;;); }
void b6 (void) { for (enum { zero, ten = 10 } i;;); }
-void b7 (void) { for (struct s { int i; };;); } // expected-error {{non-variable declaration in 'for' loop}}
-void b8 (void) { for (static struct { int i; } s;;); } // expected-error {{declaration of non-local variable}}
+void b7 (void) { for (struct s { int i; };;); } /* 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}} */
+void b8 (void) { for (static struct { int i; } s;;); } /* 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}} */
void b9 (void) { for (struct { int i; } (*s)(struct { int j; } o) = 0;;); }
-void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } // expected-error {{non-variable declaration in 'for' loop}}
+void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } /* 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}} */
More information about the cfe-commits
mailing list