diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-09-16 01:51:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-09-16 01:51:54 +0000 |
commit | abf4a3e4c605b90bba8091457ebac400eac10706 (patch) | |
tree | 97736c7e707c67d128305da87f1aeb01bb2b87f0 /clang/lib/Parse/ParseExpr.cpp | |
parent | 2cd7a78c760d1c8052fed67317de2abf2844c5ef (diff) | |
download | bcm5719-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.cpp | 58 |
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(); |