summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-15 23:19:31 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-15 23:19:31 +0000
commit3e972009fb4f93d34f3968e82e0141a3715e1259 (patch)
tree59d6ba1726f848ea0928da9749f7e81d097dc1f2
parentd3ac0c1e9cb78dcea5e925cb413771d8cd8658fd (diff)
downloadbcm5719-llvm-3e972009fb4f93d34f3968e82e0141a3715e1259.tar.gz
bcm5719-llvm-3e972009fb4f93d34f3968e82e0141a3715e1259.zip
Handle bracket insertion for Objective-C class messages in a very
narrow, almost useless case where we're inside a parenthesized expression, e.g., (NSArray alloc]) The solution to the general case still eludes me. llvm-svn: 114039
-rw-r--r--clang/lib/Parse/ParseExpr.cpp86
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp12
-rw-r--r--clang/test/FixIt/fixit-objc-message.m1
-rw-r--r--clang/test/Index/complete-objc-message.m2
4 files changed, 57 insertions, 44 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 26563de2b25..33c7d67ce14 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1529,51 +1529,63 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Ty = ParseTypeName();
}
- // Match the ')'.
- if (Tok.is(tok::r_paren))
- RParenLoc = ConsumeParen();
- else
- MatchRHSPunctuation(tok::r_paren, OpenLoc);
+ // If our type is followed by an identifier and either ':' or ']', then
+ // this is probably an Objective-C message send where the leading '[' is
+ // missing. Recover as if that were the case.
+ if (!Ty.isInvalid() && Tok.is(tok::identifier) && !InMessageExpression &&
+ getLang().ObjC1 && !Ty.get().get().isNull() &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square)) &&
+ Ty.get().get()->isObjCObjectOrInterfaceType()) {
+ Result = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
+ Ty.get(), 0);
+ } else {
+ // Match the ')'.
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, OpenLoc);
+
+ if (Tok.is(tok::l_brace)) {
+ ExprType = CompoundLiteral;
+ return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
+ }
- if (Tok.is(tok::l_brace)) {
- ExprType = CompoundLiteral;
- return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
- }
+ if (ExprType == CastExpr) {
+ // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
- if (ExprType == CastExpr) {
- // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
+ if (Ty.isInvalid())
+ return ExprError();
- if (Ty.isInvalid())
- return ExprError();
+ CastTy = Ty.get();
- CastTy = Ty.get();
+ // Note that this doesn't parse the subsequent cast-expression, it just
+ // returns the parsed type to the callee.
+ if (stopIfCastExpr)
+ return ExprResult();
+
+ // Reject the cast of super idiom in ObjC.
+ if (Tok.is(tok::identifier) && getLang().ObjC1 &&
+ Tok.getIdentifierInfo() == Ident_super &&
+ getCurScope()->isInObjcMethodScope() &&
+ GetLookAheadToken(1).isNot(tok::period)) {
+ Diag(Tok.getLocation(), diag::err_illegal_super_cast)
+ << SourceRange(OpenLoc, RParenLoc);
+ return ExprError();
+ }
- // Note that this doesn't parse the subsequent cast-expression, it just
- // returns the parsed type to the callee.
- if (stopIfCastExpr)
- return ExprResult();
-
- // Reject the cast of super idiom in ObjC.
- if (Tok.is(tok::identifier) && getLang().ObjC1 &&
- Tok.getIdentifierInfo() == Ident_super &&
- getCurScope()->isInObjcMethodScope() &&
- GetLookAheadToken(1).isNot(tok::period)) {
- Diag(Tok.getLocation(), diag::err_illegal_super_cast)
- << SourceRange(OpenLoc, RParenLoc);
- return ExprError();
+ // Parse the cast-expression that follows it next.
+ // TODO: For cast expression with CastTy.
+ Result = ParseCastExpression(false, false, CastTy);
+ if (!Result.isInvalid())
+ Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy,
+ RParenLoc, Result.take());
+ return move(Result);
}
- // Parse the cast-expression that follows it next.
- // TODO: For cast expression with CastTy.
- Result = ParseCastExpression(false, false, CastTy);
- if (!Result.isInvalid())
- Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy, RParenLoc,
- Result.take());
- return move(Result);
+ Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
+ return ExprError();
}
-
- Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
- return ExprError();
} else if (TypeOfCast) {
// Parse the expression-list.
InMessageExpressionRAIIObject InMessage(*this, false);
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index ebeed130e30..caa2762d7fc 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -786,12 +786,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
ExprResult Sema::ActOnClassMessage(Scope *S,
- ParsedType Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
TypeSourceInfo *ReceiverTypeInfo;
QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
if (ReceiverType.isNull())
diff --git a/clang/test/FixIt/fixit-objc-message.m b/clang/test/FixIt/fixit-objc-message.m
index 72728d20adc..1969faab3b8 100644
--- a/clang/test/FixIt/fixit-objc-message.m
+++ b/clang/test/FixIt/fixit-objc-message.m
@@ -21,6 +21,7 @@ void f(A *a, int i, int j) {
int array[17];
(void)array[a method1:5+2 second:+(3.14159)]];
+ (A method2:5+2 second:3.14159])
}
@interface B : A
diff --git a/clang/test/Index/complete-objc-message.m b/clang/test/Index/complete-objc-message.m
index d6abd4bd83f..02d7f2140cf 100644
--- a/clang/test/Index/complete-objc-message.m
+++ b/clang/test/Index/complete-objc-message.m
@@ -135,7 +135,7 @@ void test_ranking(B *b) {
b method1];
}
-void test_overload_2(Overload *ovl) {
+void test_overload3(Overload *ovl) {
ovl Method:1 Arg1:1 OtherArg:ovl];
}
OpenPOWER on IntegriCloud