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(DI); + for (auto Iter = DS->decl_begin(), End = DS->decl_end(); Iter != End; + ++Iter) { + VarDecl *VD = dyn_cast(*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(*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(*(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(); + } } } } 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}}