[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