Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -1822,15 +1822,27 @@ // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or // 'register'. + const Decl *NonVarSeen = nullptr; + bool VarDeclSeen = false; for (auto *DI : DS->decls()) { - VarDecl *VD = dyn_cast(DI); - if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) - VD = nullptr; - if (!VD) { - Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); - DI->setInvalidDecl(); + if (VarDecl *VD = dyn_cast(DI)) { + VarDeclSeen = true; + if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) { + Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); + DI->setInvalidDecl(); + } + } else if (!NonVarSeen) { + // Keep track of the first non-variable declaration we saw so that + // we can diagnose if we don't see any variable declarations. This + // covers a case like declaring a typedef, function, or structure + // type rather than a variable. + NonVarSeen = DI; } } + // Diagnose if we saw a non-variable declaration but no variable + // declarations. + if (NonVarSeen && !VarDeclSeen) + Diag(NonVarSeen->getLocation(), diag::err_non_variable_decl_in_for); } } Index: clang/test/Sema/for.c =================================================================== --- clang/test/Sema/for.c +++ clang/test/Sema/for.c @@ -2,6 +2,12 @@ // Check C99 6.8.5p3 void b1 (void) { for (void (*f) (void);;); } -void b2 (void) { for (void f (void);;); } // expected-error {{declaration of non-local variable}} +void b2 (void) { for (void f (void);;); } // expected-error {{non-variable declaration in 'for' loop}} 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 b4 (void) { for (typedef int f;;); } // expected-error {{non-variable declaration in 'for' loop}} +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}} +void b9 (void) { for (struct { int i; } (*s)(struct { int j; } o) = 0;;); } +void b10(void) { for (typedef struct { int i; } (*s)(struct { int j; });;); } // expected-error {{non-variable declaration in 'for' loop}}