forked from OSchip/llvm-project
hoist some code for handling objc foreach construct out of Declaration processing
into ParseForStatement. Merge two tests into one. llvm-svn: 68010
This commit is contained in:
parent
efb0f111f1
commit
32dc41c445
|
@ -809,7 +809,8 @@ private:
|
|||
// C99 6.7: Declarations.
|
||||
|
||||
DeclGroupPtrTy ParseDeclaration(unsigned Context);
|
||||
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context);
|
||||
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
|
||||
bool RequireSemi = true);
|
||||
DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
|
||||
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
|
||||
void ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
|
|
|
@ -257,7 +257,11 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) {
|
|||
/// declaration-specifiers init-declarator-list[opt] ';'
|
||||
///[C90/C++]init-declarator-list ';' [TODO]
|
||||
/// [OMP] threadprivate-directive [TODO]
|
||||
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
|
||||
///
|
||||
/// If RequireSemi is false, this does not check for a ';' at the end of the
|
||||
/// declaration.
|
||||
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
|
||||
bool RequireSemi) {
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS;
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
@ -275,22 +279,16 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
|
|||
|
||||
DeclGroupPtrTy DG =
|
||||
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
|
||||
|
||||
// If the client wants to check what comes after the declaration, just return
|
||||
// immediately without checking anything!
|
||||
if (!RequireSemi) return DG;
|
||||
|
||||
if (Tok.is(tok::semi)) {
|
||||
ConsumeToken();
|
||||
// for(is key; in keys) is error.
|
||||
if (Context == Declarator::ForContext && isTokIdentifier_in())
|
||||
Diag(Tok, diag::err_parse_error);
|
||||
|
||||
return DG;
|
||||
}
|
||||
|
||||
// If this is an ObjC2 for-each loop, this is a successful declarator
|
||||
// parse. The syntax for these looks like:
|
||||
// 'for' '(' declaration 'in' expr ')' statement
|
||||
if (Context == Declarator::ForContext && isTokIdentifier_in())
|
||||
return DG;
|
||||
|
||||
Diag(Tok, diag::err_expected_semi_declation);
|
||||
// Skip to end of block or statement
|
||||
SkipUntil(tok::r_brace, true, true);
|
||||
|
|
|
@ -912,12 +912,18 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
|
|||
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
|
||||
|
||||
SourceLocation DeclStart = Tok.getLocation();
|
||||
DeclGroupPtrTy VarDecls = ParseSimpleDeclaration(Declarator::ForContext);
|
||||
// FIXME: Pass in the right location for the end of the declstmt.
|
||||
FirstPart = Actions.ActOnDeclStmt(VarDecls, DeclStart, DeclStart);
|
||||
if ((ForEach = isTokIdentifier_in())) {
|
||||
DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, false);
|
||||
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
|
||||
|
||||
if (Tok.is(tok::semi)) { // for (int x = 4;
|
||||
ConsumeToken();
|
||||
} else if ((ForEach = isTokIdentifier_in())) {
|
||||
// ObjC: for (id x in expr)
|
||||
ConsumeToken(); // consume 'in'
|
||||
SecondPart = ParseExpression();
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_semi_for);
|
||||
SkipUntil(tok::semi);
|
||||
}
|
||||
} else {
|
||||
Value = ParseExpression();
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
ce MyList // expected-error {{invalid token after top level declarator}}
|
||||
@end
|
||||
|
||||
|
||||
@implementation MyList
|
||||
- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
int LOOP();
|
||||
|
||||
@implementation MyList (BasicTest) // expected-error {{cannot find interface declaration for 'MyList'}}
|
||||
- (void)compilerTestAgainst {
|
||||
MyList * el; // expected-error {{use of undeclared identifier 'MyList'}}
|
||||
for (el in @"foo") // expected-error {{use of undeclared identifier 'el'}}
|
||||
{ LOOP(); }
|
||||
}
|
||||
@end
|
||||
|
|
@ -1,7 +1,28 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
static int test_NSURLGetResourceValueForKey( id keys )
|
||||
ce MyList // expected-error {{invalid token after top level declarator}}
|
||||
@end
|
||||
|
||||
|
||||
@implementation MyList
|
||||
- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount
|
||||
{
|
||||
for ( id key; in keys) { // expected-error {{parse error}}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
int LOOP();
|
||||
|
||||
@implementation MyList (BasicTest) // expected-error {{cannot find interface declaration for 'MyList'}}
|
||||
- (void)compilerTestAgainst {
|
||||
MyList * el; // expected-error {{use of undeclared identifier 'MyList'}}
|
||||
for (el in @"foo") // expected-error {{use of undeclared identifier 'el'}}
|
||||
{ LOOP(); }
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
static int test7(id keys) {
|
||||
for (id key; in keys) ; // expected-error {{use of undeclared identifier 'in'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue