summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseExpr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-16 01:51:54 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-16 01:51:54 +0000
commitabf4a3e4c605b90bba8091457ebac400eac10706 (patch)
tree97736c7e707c67d128305da87f1aeb01bb2b87f0 /clang/lib/Parse/ParseExpr.cpp
parent2cd7a78c760d1c8052fed67317de2abf2844c5ef (diff)
downloadbcm5719-llvm-abf4a3e4c605b90bba8091457ebac400eac10706.tar.gz
bcm5719-llvm-abf4a3e4c605b90bba8091457ebac400eac10706.zip
Implement automatic bracket insertion for Objective-C class message
sends. These are far trickier than instance messages, because we typically have something like NSArray alloc] where it appears to be a declaration of a variable named "alloc" up until we see the ']' (or a ':'), and at that point we can't backtrace. So, we use a combination of syntactic and semantic disambiguation to treat this as a message send only when the type is an Objective-C type and it has the syntax of a class message send (which would otherwise be ill-formed). llvm-svn: 114057
Diffstat (limited to 'clang/lib/Parse/ParseExpr.cpp')
-rw-r--r--clang/lib/Parse/ParseExpr.cpp58
1 files changed, 56 insertions, 2 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 33c7d67ce14..be468d537d7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -677,6 +677,35 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
break;
}
+ // If we have an Objective-C class name followed by an identifier and
+ // either ':' or ']', this is an Objective-C class message send that's
+ // missing the opening '['. Recovery appropriately.
+ if (getLang().ObjC1 && Tok.is(tok::identifier)) {
+ const Token& Next = NextToken();
+ if (Next.is(tok::colon) || Next.is(tok::r_square))
+ if (ParsedType Type = Actions.getTypeName(II, ILoc, getCurScope()))
+ if (Type.get()->isObjCObjectOrInterfaceType()) {
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(ILoc);
+ DS.SetRangeEnd(ILoc);
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Type);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
+ DeclaratorInfo);
+ if (Ty.isInvalid())
+ break;
+
+ Res = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
+ Ty.get(), 0);
+ break;
+ }
+ }
+
// Make sure to pass down the right value for isAddressOfOperand.
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
isAddressOfOperand = false;
@@ -791,6 +820,32 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = ParseCXXThis();
break;
+ case tok::annot_typename:
+ if (isStartOfObjCClassMessageMissingOpenBracket()) {
+ ParsedType Type = getTypeAnnotation(Tok);
+
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(Tok.getLocation());
+ DS.SetRangeEnd(Tok.getLastLoc());
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, Tok.getLocation(), PrevSpec, DiagID,
+ Type);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ if (Ty.isInvalid())
+ break;
+
+ ConsumeToken();
+ Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
+ Ty.get(), 0);
+ break;
+ }
+ // Fall through
+
case tok::kw_char:
case tok::kw_wchar_t:
case tok::kw_char16_t:
@@ -806,8 +861,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_void:
case tok::kw_typename:
case tok::kw_typeof:
- case tok::kw___vector:
- case tok::annot_typename: {
+ case tok::kw___vector: {
if (!getLang().CPlusPlus) {
Diag(Tok, diag::err_expected_expression);
return ExprError();
OpenPOWER on IntegriCloud