diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-03-20 18:09:33 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-03-20 18:09:33 +0000 |
commit | 4cc0cf1a54541b26b258c45cd7a3c80c9401eaad (patch) | |
tree | be19b75e1fa768f458eabd63b06677ffd18c4969 | |
parent | 36771d910b049cc534841c48ced90772784af446 (diff) |
Objective-C [qoi] more gracefull recovery when
'}' is missing for the ivar declarations.
// rdar://6854840
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177549 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 4 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 45 | ||||
-rw-r--r-- | test/Parser/missing-closing-rbrace.m | 14 |
3 files changed, 42 insertions, 21 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index d8220b3ba5..5205105434 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index b95b41f722..badbee2b5b 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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; } diff --git a/test/Parser/missing-closing-rbrace.m b/test/Parser/missing-closing-rbrace.m index ae1291e1e3..89c1f18cda 100644 --- a/test/Parser/missing-closing-rbrace.m +++ b/test/Parser/missing-closing-rbrace.m @@ -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 |