From: Chris Lattner Date: Wed, 22 Apr 2009 00:54:41 +0000 (+0000) Subject: Fix a problem with objc foreach loop. It turns out that objc mode changes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d00f2a5a9b670cd0d67d640a42dbf7b9f342c59;p=clang Fix a problem with objc foreach loop. It turns out that objc mode changes for scoping to match C99 even when in C89 mode. This patch fixes this (eliminating a "redefinition of thisKey" error), and also prevents non-sensical diagnostics in -pedantic mode like this: t.m:7:8: warning: variable declaration in for loop is a C99-specific feature for (id thisKey in keys) ; ^ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69760 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b87ede9388..fa712e0a9e 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -867,7 +867,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() { return StmtError(); } - bool C99orCXX = getLang().C99 || getLang().CPlusPlus; + bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1; // C99 6.8.5p5 - In C99, the for statement is a block. This is not // the case for C90. Start the loop scope. @@ -885,7 +885,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() { // as those declared in the condition. // unsigned ScopeFlags; - if (C99orCXX) + if (C99orCXXorObjC) ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope | Scope::ControlScope; else @@ -906,7 +906,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() { ConsumeToken(); } else if (isSimpleDeclaration()) { // for (int X = 4; // Parse declaration, which eats the ';'. - if (!C99orCXX) // Use of C99-style for loops in C90 mode? + if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; @@ -976,7 +976,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() { // for-init-statement/condition and a new scope for substatement in C++. // ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + C99orCXXorObjC && Tok.isNot(tok::l_brace)); // Read the body statement. OwningStmtResult Body(ParseStatement()); diff --git a/test/SemaObjC/foreach-1.m b/test/SemaObjC/foreach-1.m index d3ca424a04..f136adfa36 100644 --- a/test/SemaObjC/foreach-1.m +++ b/test/SemaObjC/foreach-1.m @@ -1,10 +1,18 @@ -// RUN: clang-cc -fsyntax-only -verify %s +/* RUN: clang-cc -fsyntax-only -verify -std=c89 -pedantic %s + */ @class NSArray; -void f(NSArray *a) -{ - for (int i in a); // expected-error{{selector element type 'int' is not a valid object}} - for ((id)2 in a); // expected-error{{selector element is not a valid lvalue}} - for (2 in a); // expected-error{{selector element is not a valid lvalue}} +void f(NSArray *a) { + id keys; + for (int i in a); /* expected-error{{selector element type 'int' is not a valid object}} */ + for ((id)2 in a); /* expected-error{{selector element is not a valid lvalue}} */ + for (2 in a); /* expected-error{{selector element is not a valid lvalue}} */ + + /* This should be ok, 'thisKey' should be scoped to the loop in question, + * and no diagnostics even in pedantic mode should happen. + * rdar://6814674 + */ + for (id thisKey in keys); + for (id thisKey in keys); }