[PATCH] D92577: Don't reject tag declarations in for loop clause-1
Aaron Ballman via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 17 07:25:05 PST 2020
aaron.ballman updated this revision to Diff 312494.
aaron.ballman added a comment.
Updating based on review feedback.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D92577/new/
https://reviews.llvm.org/D92577
Files:
clang/lib/Sema/SemaStmt.cpp
clang/test/Sema/for.c
Index: clang/test/Sema/for.c
===================================================================
--- clang/test/Sema/for.c
+++ clang/test/Sema/for.c
@@ -5,3 +5,7 @@
void b2 (void) { for (void f (void);;); } // expected-error {{declaration of non-local variable}}
void b3 (void) { for (static int f;;); } // expected-error {{declaration of non-local variable}}
void b4 (void) { for (typedef int f;;); } // expected-error {{declaration of non-local variable}}
+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}}
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -1822,13 +1822,28 @@
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
- for (auto *DI : DS->decls()) {
- VarDecl *VD = dyn_cast<VarDecl>(DI);
+ for (auto Iter = DS->decl_begin(), End = DS->decl_end(); Iter != End;
+ ++Iter) {
+ VarDecl *VD = dyn_cast<VarDecl>(*Iter);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
VD = nullptr;
+
if (!VD) {
- Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
- DI->setInvalidDecl();
+ // It is possible to declare non-variable declarations as part of the
+ // declaration part of a 'for' statement, such as defining a structure
+ // or enum type: for (enum { zero, ten } i = zero; i < ten; ++i);
+ if (isa<TagDecl>(*Iter)) {
+ // The declaration immediately after the tag decl needs to be a
+ // variable declaration. We don't care if it's a valid variable
+ // declaration because the validity will be checked on the next
+ // iteration through the declarations in the group.
+ if (Iter + 1 == End || !isa<VarDecl>(*(Iter + 1)))
+ Diag((*Iter)->getLocation(), diag::err_non_variable_decl_in_for);
+ } else {
+ Diag((*Iter)->getLocation(),
+ diag::err_non_local_variable_decl_in_for);
+ (*Iter)->setInvalidDecl();
+ }
}
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D92577.312494.patch
Type: text/x-patch
Size: 2535 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201217/98dc5a75/attachment.bin>
More information about the cfe-commits
mailing list