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