]> granicus.if.org Git - clang/commitdiff
Handle bracket insertion for Objective-C class messages in a very
authorDouglas Gregor <dgregor@apple.com>
Wed, 15 Sep 2010 23:19:31 +0000 (23:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 15 Sep 2010 23:19:31 +0000 (23:19 +0000)
narrow, almost useless case where we're inside a parenthesized
expression, e.g.,

  (NSArray alloc])

The solution to the general case still eludes me.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114039 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseExpr.cpp
lib/Sema/SemaExprObjC.cpp
test/FixIt/fixit-objc-message.m
test/Index/complete-objc-message.m

index 26563de2b258e9ff3c6843ab4298ea61ca8da546..33c7d67ce1458b765c4dd4e9bf99d152f698c669 100644 (file)
@@ -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);
index ebeed130e301a9ab072b8e522cf78ec13e7a82da..caa2762d7fc03577ce6320d897cabdddfdb79f56 100644 (file)
@@ -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())
index 72728d20adc74d97ce413a7058937c6310cc552d..1969faab3b81fd0fbcfc72567a630771013b249f 100644 (file)
@@ -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
index d6abd4bd83fd5517d5b952939c373238bbdfed32..02d7f2140cf6668084c67b99865754ea725efde3 100644 (file)
@@ -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];
 }