Objective-C [qoi] more gracefull recovery when

'}' is missing for the ivar declarations.
// rdar://6854840

llvm-svn: 177549
This commit is contained in:
Fariborz Jahanian 2013-03-20 18:09:33 +00:00
parent ecfe21b792
commit 089f39ec06
3 changed files with 42 additions and 21 deletions

View File

@ -1115,6 +1115,10 @@ private:
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParsedAttributes &prefixAttrs);
void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
SmallVectorImpl<Decl *> &AllIvarDecls,
bool RBraceMissing);
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc);

View File

@ -1228,6 +1228,22 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
return Result;
}
void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
SmallVectorImpl<Decl *> &AllIvarDecls,
bool RBraceMissing) {
if (!RBraceMissing)
T.consumeClose();
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
Actions.ActOnObjCContainerFinishDefinition();
// Call ActOnFields() even if we don't have any decls. This is useful
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
AllIvarDecls,
T.getOpenLocation(), T.getCloseLocation(), 0);
}
/// objc-class-instance-variables:
/// '{' objc-instance-variable-decl-list[opt] '}'
@ -1260,7 +1276,6 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
// While we still have something to read, read the instance variables.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one objc-instance-variable-decl.
@ -1288,13 +1303,17 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
visibility = Tok.getObjCKeywordID();
ConsumeToken();
continue;
case tok::objc_end:
Diag(Tok, diag::err_objc_unexpected_atend);
ConsumeToken();
continue;
default:
Diag(Tok, diag::err_objc_illegal_visibility_spec);
continue;
Diag(Tok, (Tok.getObjCKeywordID() == tok::objc_end) ?
diag::err_objc_unexpected_atend :
diag::err_objc_illegal_visibility_spec);
Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
Tok.setKind(tok::at);
Tok.setLength(1);
PP.EnterToken(Tok);
HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
T, AllIvarDecls, true);
return;
}
}
@ -1341,16 +1360,8 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
SkipUntil(tok::r_brace, true, true);
}
}
T.consumeClose();
Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
Actions.ActOnObjCContainerFinishDefinition();
// Call ActOnFields() even if we don't have any decls. This is useful
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
AllIvarDecls,
T.getOpenLocation(), T.getCloseLocation(), 0);
HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
T, AllIvarDecls, false);
return;
}

View File

@ -1,6 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar: //6854840
@interface A {@end // expected-error {{'@end' appears where closing brace '}' is expected}}\
// expected-note {{to match this '{'}}\
// expected-note {{class started here}}
// expected-error {{expected '}'}} expected-error {{missing '@end'}}
@interface A {@end // expected-error {{'@end' appears where closing brace '}' is expected}}
@interface B {
@public
int ivar;
@protected
id pp;
@property (copy) id PROP; // expected-error {{illegal visibility specification}}
@end