https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/129737
>From f0605e803b6e7748913515a4b0ffe34fa7eedc24 Mon Sep 17 00:00:00 2001 From: Sirraide <aeternalm...@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 <aeternalm...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits