aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-05-31 14:40:22 +0000
committerDouglas Gregor <dgregor@apple.com>2010-05-31 14:40:22 +0000
commit1b730e847ded503f2e615154035c083c4f94a067 (patch)
tree38ee34eea94d38a2daac2313e5765ec17290a824
parent5b013df7d194ddaf030177387789c3c8248852b2 (diff)
When we see the a '[' in a postfix expression in Objective-C, perform
a simple, quick check to determine whether the expression starting with '[' can only be an Objective-C message send. If so, don't parse it as an array subscript expression. This improves recovery for, e.g., [a method1] [a method2] so that we now produce t.m:10:13: error: expected ';' after expression [a method] ^ instead of some mess about expecting ']'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105221 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/Parser.h1
-rw-r--r--lib/Parse/ParseExpr.cpp3
-rw-r--r--lib/Parse/ParseObjc.cpp15
-rw-r--r--test/FixIt/typo.m8
4 files changed, 26 insertions, 1 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 8081c2492b..233ed1c0b8 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1059,6 +1059,7 @@ private:
OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ bool isSimpleObjCMessageExpression();
OwningExprResult ParseObjCMessageExpression();
OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
SourceLocation SuperLoc,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 8fb71c3ff6..093f9738ca 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -961,6 +961,9 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
default: // Not a postfix-expression suffix.
return move(LHS);
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
+ if (getLang().ObjC1 && isSimpleObjCMessageExpression())
+ return move(LHS);
+
Loc = ConsumeBracket();
OwningExprResult Idx(ParseExpression());
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index b76b677af0..34b8187be5 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1794,6 +1794,21 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
return false;
}
+/// \brief Determine whether the parser is currently referring to a an
+/// Objective-C message send, using a simplified heuristic to avoid overhead.
+///
+/// This routine will only return true for a subset of valid message-send
+/// expressions.
+bool Parser::isSimpleObjCMessageExpression() {
+ assert(Tok.is(tok::l_square) &&
+ "Incorrect start for isSimpleObjCMessageExpression");
+ if (!getLang().ObjC1)
+ return false;
+
+ return GetLookAheadToken(1).is(tok::identifier) &&
+ GetLookAheadToken(2).is(tok::identifier);
+}
+
/// objc-message-expr:
/// '[' objc-receiver objc-message-args ']'
///
diff --git a/test/FixIt/typo.m b/test/FixIt/typo.m
index 7197bc746d..8a9b4c804c 100644
--- a/test/FixIt/typo.m
+++ b/test/FixIt/typo.m
@@ -24,7 +24,8 @@ void test() {
int his_ivar; // expected-note 2{{'his_ivar' declared here}}
float wibble;
}
-
+- (void)method;
++ (void)method;
@property int his_prop; // expected-note{{'his_prop' declared here}}
@end
@@ -145,4 +146,9 @@ double *isupper(int);
@end
#endif
+void f(A *a) {
+ f(a) // expected-error{{expected ';' after expression}}
+ [a method] // expected-error{{expected ';' after expression}}
+ [A method] // expected-error{{expected ';' after expression}}
+}