[clang] [Clang] [Sema] Allow non-local/non-variable declarations in for loop (PR #129737)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 5 11:06:57 PST 2025


https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/129737

>From f0605e803b6e7748913515a4b0ffe34fa7eedc24 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 4 Mar 2025 17:36:30 +0100
Subject: [PATCH 1/2] [Clang] Allow non-local/non-variable declarations in for
 loop

---
 clang/docs/ReleaseNotes.rst                   |  2 ++
 .../clang/Basic/DiagnosticSemaKinds.td        | 17 ++++++++++++++
 clang/lib/Sema/SemaStmt.cpp                   | 13 ++++++-----
 clang/test/Sema/for.c                         | 22 +++++++++++++------
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 97b8e32f03b57..cf205e7064aa8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Bug Fixes in This Version
   when it can affect template argument deduction (#GH122306).
 - Fix crash on code completion of function calls involving partial order of function templates
   (#GH125500).
+- Non-local variable and non-variable declarations in the first clause of a ``for`` loop in C are no longer erroneously
+  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 d89648a8a2e83..c87ef62310cb9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10794,6 +10794,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}} */

>From 3ab8a48d7d7c050e7a8a1ed98a2fb84a0e2e79c5 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 5 Mar 2025 20:06:47 +0100
Subject: [PATCH 2/2] Update release notes

---
 clang/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cf205e7064aa8..160a5947d6a50 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,7 +237,7 @@ Bug Fixes in This Version
   when it can affect template argument deduction (#GH122306).
 - Fix crash on code completion of function calls involving partial order of function templates
   (#GH125500).
-- Non-local variable and non-variable declarations in the first clause of a ``for`` loop in C are no longer erroneously
+- 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



More information about the cfe-commits mailing list