aaron.ballman created this revision.
aaron.ballman added reviewers: rsmith, rjmccall.
aaron.ballman requested review of this revision.

We currently reject this valid C construct by claiming it declares a non-local 
variable: `for (struct { int i; } s={0}; s.i != 0; s.i--) ;`

The problem is that we expect all declaration in the clause-1 declaration 
statement to be `VarDecl`s of local variables, but there can be other 
declarations involved such as a tag declaration. We now ignore tag declarations 
when deciding whether the clause-1 declarations are valid or not. This fixes 
PR35757.


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,5 @@
 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;;); }
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -1826,7 +1826,10 @@
         VarDecl *VD = dyn_cast<VarDecl>(DI);
         if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
           VD = nullptr;
-        if (!VD) {
+        // 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 (!VD && !isa<TagDecl>(DI)) {
           Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
           DI->setInvalidDecl();
         }


Index: clang/test/Sema/for.c
===================================================================
--- clang/test/Sema/for.c
+++ clang/test/Sema/for.c
@@ -5,3 +5,5 @@
 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;;); }
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -1826,7 +1826,10 @@
         VarDecl *VD = dyn_cast<VarDecl>(DI);
         if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
           VD = nullptr;
-        if (!VD) {
+        // 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 (!VD && !isa<TagDecl>(DI)) {
           Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for);
           DI->setInvalidDecl();
         }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to