aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-03-20 18:09:33 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-03-20 18:09:33 +0000
commit4cc0cf1a54541b26b258c45cd7a3c80c9401eaad (patch)
treebe19b75e1fa768f458eabd63b06677ffd18c4969
parent36771d910b049cc534841c48ced90772784af446 (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.h4
-rw-r--r--lib/Parse/ParseObjc.cpp45
-rw-r--r--test/Parser/missing-closing-rbrace.m14
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