]> granicus.if.org Git - clang/commitdiff
Rework the Parser-Sema interaction for Objective-C message
authorDouglas Gregor <dgregor@apple.com>
Wed, 21 Apr 2010 19:57:20 +0000 (19:57 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 21 Apr 2010 19:57:20 +0000 (19:57 +0000)
sends. Major changes include:

  - Expanded the interface from two actions (ActOnInstanceMessage,
    ActOnClassMessage), where ActOnClassMessage also handled sends to
    "super" by checking whether the identifier was "super", to three
    actions (ActOnInstanceMessage, ActOnClassMessage,
    ActOnSuperMessage). Code completion has the same changes.
  - The parser now resolves the type to which we are sending a class
    message, so ActOnClassMessage now accepts a TypeTy* (rather than
    an IdentifierInfo *). This opens the door to more interesting
    types (for Objective-C++ support).
  - Split ActOnInstanceMessage and ActOnClassMessage into parser
    action functions (with their original names) and semantic
    functions (BuildInstanceMessage and BuildClassMessage,
    respectively). At present, this split is onyl used by
    ActOnSuperMessage, which decides which kind of super message it
    has and forwards to the appropriate Build*Message. In the future,
    Build*Message will be used by template instantiation.
  - Use getObjCMessageKind() within the disambiguation of Objective-C
    message sends vs. array designators.

Two notes about substandard bits in this patch:
  - There is some redundancy in the code in ParseObjCMessageExpr and
  ParseInitializerWithPotentialDesignator; this will be addressed
  shortly by centralizing the mapping from identifiers to type names
  for the message receiver.
  - There is some #if 0'd code that won't likely ever be used---it
  handles the use of 'super' in methods whose class does not have a
  superclass---but could be used to model GCC's behavior more
  closely. This code will die in my next check-in, but I want it in
  Subversion.

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

13 files changed:
include/clang/AST/ExprObjC.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/Parse/ParseExpr.cpp
lib/Parse/ParseInit.cpp
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.h
lib/Sema/SemaCodeComplete.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/invalid-receiver.m
test/SemaObjC/super.m
test/SemaObjCXX/message.mm

index 7aed6cabef39e7e6603fbbd708bbb28d12f7100a..04b2c20b85eea1517d52722aab74aed98d69ae92 100644 (file)
@@ -343,6 +343,29 @@ public:
   virtual child_iterator child_end();
 };
 
+/// \brief An expression that sends a message to the given Objective-C
+/// object or class.
+///
+/// The following contains two message send expressions:
+///
+/// \code
+///   [[NSString alloc] initWithString:@"Hello"]
+/// \endcode
+///
+/// The innermost message send invokes the "alloc" class method on the
+/// NSString class, while the outermost message send invokes the
+/// "initWithString" instance method on the object returned from
+/// NSString's "alloc". In all, an Objective-C message send can take
+/// on four different (although related) forms:
+///
+///   1. Send to an object instance.
+///   2. Send to a class.
+///   3. Send to the superclass instance of the current class.
+///   4. Send to the superclass of the current class.
+///
+/// All four kinds of message sends are modeled by the ObjCMessageExpr
+/// class, and can be distinguished via \c getReceiverKind(). Example:
+///
 class ObjCMessageExpr : public Expr {
   /// \brief The number of arguments in the message send, not
   /// including the receiver.
@@ -402,7 +425,7 @@ class ObjCMessageExpr : public Expr {
                   Expr **Args, unsigned NumArgs,
                   SourceLocation RBracLoc);
 
-  /// \brief Retrieve the pointer value of the ,message receiver.
+  /// \brief Retrieve the pointer value of the message receiver.
   void *getReceiverPointer() const {
     return *const_cast<void **>(
                              reinterpret_cast<const void * const*>(this + 1));
@@ -712,6 +735,9 @@ public:
 
 /// ObjCSuperExpr - Represents the "super" expression in Objective-C,
 /// which refers to the object on which the current method is executing.
+///
+/// FIXME: This class is intended for removal, once its remaining
+/// clients have been altered to represent "super" internally.
 class ObjCSuperExpr : public Expr {
   SourceLocation Loc;
 public:
index 7919d8247a75ec60b62c57ad8d6094698eaa5066..a5be82df86093209061e6503b21bc51e870c1f42 100644 (file)
@@ -2046,6 +2046,8 @@ def err_invalid_receiver_to_message : Error<
   "invalid receiver to message expression">;
 def err_invalid_receiver_to_message_super : Error<
   "'super' is only valid in a method body">;
+def err_invalid_receiver_class_message : Error<
+  "receiver type %0 is not an Objective-C class">;
 def warn_bad_receiver_type : Warning<
   "receiver type %0 is not 'id' or interface pointer, consider "
   "casting it to 'id'">;
index 65a8769b9b7c88868bd47a8666b295cee0d48c14..66ef8d0c672ced1afcd5725abbba083b1647e3c9 100644 (file)
@@ -2389,29 +2389,63 @@ public:
                                              SourceLocation NameLoc,
                                              bool IsSuper,
                                              bool HasTrailingDot);
-  
-  // ActOnClassMessage - used for both unary and keyword messages.
-  // ArgExprs is optional - if it is present, the number of expressions
-  // is obtained from NumArgs.
-  virtual ExprResult ActOnClassMessage(
-    Scope *S,
-    IdentifierInfo *receivingClassName,
-    Selector Sel,
-    SourceLocation lbrac, SourceLocation receiverLoc,
-    SourceLocation selectorLoc,
-    SourceLocation rbrac,
-    ExprTy **ArgExprs, unsigned NumArgs) {
-    return ExprResult();
-  }
-  // ActOnInstanceMessage - used for both unary and keyword messages.
-  // ArgExprs is optional - if it is present, the number of expressions
-  // is obtained from NumArgs.
-  virtual ExprResult ActOnInstanceMessage(
-    ExprTy *receiver, Selector Sel,
-    SourceLocation lbrac, SourceLocation selectorLoc, SourceLocation rbrac,
-    ExprTy **ArgExprs, unsigned NumArgs) {
-    return ExprResult();
+
+  /// \brief Parsed a message send to 'super'.
+  ///
+  /// \param S The scope in which the message send occurs.
+  /// \param SuperLoc The location of the 'super' keyword.
+  /// \param Sel The selector to which the message is being sent.
+  /// \param LBracLoc The location of the opening square bracket ']'.
+  /// \param SelectorLoc The location of the first identifier in the selector.
+  /// \param RBrac The location of the closing square bracket ']'.
+  /// \param Args The message arguments.
+  virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                             Selector Sel,
+                                             SourceLocation LBracLoc,
+                                             SourceLocation SelectorLoc,
+                                             SourceLocation RBracLoc,
+                                             MultiExprArg Args) {
+    return OwningExprResult(*this);
+  }
+
+  /// \brief Parsed a message send to a class.
+  ///
+  /// \param S The scope in which the message send occurs.
+  /// \param Receiver The type of the class receiving the message.
+  /// \param Sel The selector to which the message is being sent.
+  /// \param LBracLoc The location of the opening square bracket ']'.
+  /// \param SelectorLoc The location of the first identifier in the selector.
+  /// \param RBrac The location of the closing square bracket ']'.
+  /// \param Args The message arguments.
+  virtual OwningExprResult ActOnClassMessage(Scope *S,
+                                             TypeTy *Receiver,
+                                             Selector Sel,
+                                             SourceLocation LBracLoc, 
+                                             SourceLocation SelectorLoc,
+                                             SourceLocation RBracLoc,
+                                             MultiExprArg Args) {
+    return OwningExprResult(*this);
+  }
+
+  /// \brief Parsed a message send to an object instance.
+  ///
+  /// \param S The scope in which the message send occurs.
+  /// \param Receiver The expression that computes the receiver object.
+  /// \param Sel The selector to which the message is being sent.
+  /// \param LBracLoc The location of the opening square bracket ']'.
+  /// \param SelectorLoc The location of the first identifier in the selector.
+  /// \param RBrac The location of the closing square bracket ']'.
+  /// \param Args The message arguments.
+  virtual OwningExprResult ActOnInstanceMessage(Scope *S,
+                                                ExprArg Receiver,
+                                                Selector Sel,
+                                                SourceLocation LBracLoc, 
+                                                SourceLocation SelectorLoc, 
+                                                SourceLocation RBracLoc,
+                                                MultiExprArg Args) {
+    return OwningExprResult(*this);
   }
+
   virtual DeclPtrTy ActOnForwardClassDeclaration(
     SourceLocation AtClassLoc,
     IdentifierInfo **IdentList,
@@ -2738,21 +2772,33 @@ public:
                                               unsigned NumMethods) {
   }
 
+  /// \brief Code completion for an ObjC message expression that sends
+  /// a message to the superclass.
+  ///
+  /// This code completion action is invoked when the code-completion token is
+  /// found after the class name and after each argument.
+  ///
+  /// \param S The scope in which the message expression occurs. 
+  /// \param SuperLoc The location of the 'super' keyword.
+  /// \param SelIdents The identifiers that describe the selector (thus far).
+  /// \param NumSelIdents The number of identifiers in \p SelIdents.
+  virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                            IdentifierInfo **SelIdents,
+                                            unsigned NumSelIdents) { }
+
   /// \brief Code completion for an ObjC message expression that refers to
   /// a class method.
   ///
   /// This code completion action is invoked when the code-completion token is
   /// found after the class name and after each argument.
   ///
-  /// \param S the scope in which the message expression occurs. 
-  /// \param FName the factory name. 
-  /// \param FNameLoc the source location of the factory name.
-  /// \param SelIdents the identifiers that describe the selector (thus far).
-  /// \param NumSelIdents the number of identifiers in \p SelIdents.
-  virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
-                                            SourceLocation FNameLoc,
+  /// \param S The scope in which the message expression occurs. 
+  /// \param Receiver The type of the class that is receiving a message.
+  /// \param SelIdents The identifiers that describe the selector (thus far).
+  /// \param NumSelIdents The number of identifiers in \p SelIdents.
+  virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
                                             IdentifierInfo **SelIdents,
-                                            unsigned NumSelIdents){ }
+                                            unsigned NumSelIdents) { }
   
   /// \brief Code completion for an ObjC message expression that refers to
   /// an instance method.
index 7e366c4d274b22cb4b8e5ac5e77b6be60d747dde..8d98f605505a3342ecaa48c66734afa212b03c29 100644 (file)
@@ -1005,12 +1005,12 @@ private:
   OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
   OwningExprResult ParseObjCMessageExpression();
   OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
-                                                  SourceLocation NameLoc,
-                                                  IdentifierInfo *ReceiverName,
+                                                  SourceLocation SuperLoc,
+                                                  TypeTy *ReceiverType,
                                                   ExprArg ReceiverExpr);
   OwningExprResult ParseAssignmentExprWithObjCMessageExprStart(
-      SourceLocation LBracloc, SourceLocation NameLoc,
-      IdentifierInfo *ReceiverName, ExprArg ReceiverExpr);
+      SourceLocation LBracloc, SourceLocation SuperLoc,
+      TypeTy *ReceiverType, ExprArg ReceiverExpr);
 
   //===--------------------------------------------------------------------===//
   // C99 6.8: Statements and Blocks.
index 27696c438f032e65a14dd910ceec124bd4d70d86..ef35dcb3f6ca25ef7d4b2e763f6dc39e0ff5459a 100644 (file)
@@ -268,11 +268,11 @@ Parser::OwningExprResult Parser::ParseAssignmentExpression() {
 /// expressions and other binary operators for these expressions as well.
 Parser::OwningExprResult
 Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
-                                                    SourceLocation NameLoc,
-                                                   IdentifierInfo *ReceiverName,
+                                                    SourceLocation SuperLoc,
+                                                    TypeTy *ReceiverType,
                                                     ExprArg ReceiverExpr) {
-  OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc,
-                                                    ReceiverName,
+  OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
+                                                    ReceiverType,
                                                     move(ReceiverExpr)));
   if (R.isInvalid()) return move(R);
   R = ParsePostfixExpressionSuffix(move(R));
@@ -481,7 +481,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
 /// [OBJC]  '@encode' '(' type-name ')'
 /// [OBJC]  objc-string-literal
 /// [C++]   simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
-/// [C++]   typename-specifier '(' expression-list[opt] ')'         [TODO]
+/// [C++]   typename-specifier '(' expression-list[opt] ')'         [C++ 5.2.3]
 /// [C++]   'const_cast' '<' type-name '>' '(' expression ')'       [C++ 5.2p1]
 /// [C++]   'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1]
 /// [C++]   'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
@@ -501,14 +501,14 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
 ///
 ///       id-expression: [C++ 5.1]
 ///                   unqualified-id
-///                   qualified-id           [TODO]
+///                   qualified-id          
 ///
 ///       unqualified-id: [C++ 5.1]
 ///                   identifier
 ///                   operator-function-id
-///                   conversion-function-id [TODO]
-///                   '~' class-name         [TODO]
-///                   template-id            [TODO]
+///                   conversion-function-id
+///                   '~' class-name        
+///                   template-id           
 ///
 ///       new-expression: [C++ 5.3.4]
 ///                   '::'[opt] 'new' new-placement[opt] new-type-id
index 123908d25a4be2328db7b96b7d0f7ee46fbba779..b0735b3cab3c1664a562e036b9ad550b68034d73 100644 (file)
@@ -129,13 +129,16 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
     // send to 'super', parse this as a message send expression.
     if (getLang().ObjC1 && Tok.is(tok::identifier)) {
       IdentifierInfo *II = Tok.getIdentifierInfo();
-
+      SourceLocation IILoc = Tok.getLocation();
       // Three cases. This is a message send to a type: [type foo]
       // This is a message send to super:  [super foo]
       // This is a message sent to an expr:  [super.bar foo]
-      if (Actions.getTypeName(*II, Tok.getLocation(), CurScope) ||
-          (II == Ident_super && GetLookAheadToken(1).isNot(tok::period) &&
-           CurScope->isInObjcMethodScope())) {
+      switch (Action::ObjCMessageKind Kind
+                = Actions.getObjCMessageKind(CurScope, II, IILoc, 
+                                             II == Ident_super,
+                                             NextToken().is(tok::period))) {
+      case Action::ObjCSuperMessage:
+      case Action::ObjCClassMessage: {
         // If we have exactly one array designator, this used the GNU
         // 'designation: array-designator' extension, otherwise there should be no
         // designators at all!
@@ -146,9 +149,47 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
         else if (Desig.getNumDesignators() > 0)
           Diag(Tok, diag::err_expected_equal_designator);
 
-        SourceLocation NameLoc = ConsumeToken();
-        return ParseAssignmentExprWithObjCMessageExprStart(
-                                       StartLoc, NameLoc, II, ExprArg(Actions));
+        if (Kind == Action::ObjCSuperMessage)
+          return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+                                                             ConsumeToken(),
+                                                             0,
+                                                             ExprArg(Actions));
+
+        // FIXME: This code is redundant with ParseObjCMessageExpr.
+        // Create the type that corresponds to the identifier (which
+        // names an Objective-C class).
+        TypeTy *Type = 0;
+        if (TypeTy *TyName = Actions.getTypeName(*II, IILoc, CurScope)) {
+          DeclSpec DS;
+          const char *PrevSpec = 0;
+          unsigned DiagID = 0;
+          if (!DS.SetTypeSpecType(DeclSpec::TST_typename, IILoc, PrevSpec,
+                                  DiagID, TyName)) {
+            DS.SetRangeEnd(IILoc);
+            Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+            TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo);
+            if (!Ty.isInvalid())
+              Type = Ty.get();
+          }
+        }
+
+        ConsumeToken(); // The identifier.
+        if (!Type) {
+          SkipUntil(tok::r_square);
+          return ExprError();
+        }
+
+        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 
+                                                           SourceLocation(), 
+                                                           Type, 
+                                                           ExprArg(Actions));
+      }
+
+      case Action::ObjCInstanceMessage:
+        // Fall through; we'll just parse the expression and
+        // (possibly) treat this like an Objective-C message send
+        // later.
+        break;
       }
     }
 
index 057907d1120f9c3ee4ecce9784e2b7088ba260cc..56937a66cdc4eff395817d85884a5be3552e9f77 100644 (file)
@@ -1714,7 +1714,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
 ///   objc-message-expr:
 ///     '[' objc-receiver objc-message-args ']'
 ///
-///   objc-receiver:
+///   objc-receiver: [C]
 ///     'super'
 ///     expression
 ///     class-name
@@ -1730,11 +1730,39 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
                                        Name == Ident_super,
                                        NextToken().is(tok::period))) {
     case Action::ObjCSuperMessage:
-    case Action::ObjCClassMessage:
-      return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), Name,
+      return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 0,
                                             ExprArg(Actions));
+
+    case Action::ObjCClassMessage: {
+      // Create the type that corresponds to the identifier (which
+      // names an Objective-C class).
+      TypeTy *Type = 0;
+      if (TypeTy *TyName = Actions.getTypeName(*Name, NameLoc, CurScope)) {
+        DeclSpec DS;
+        const char *PrevSpec = 0;
+        unsigned DiagID = 0;
+        if (!DS.SetTypeSpecType(DeclSpec::TST_typename, NameLoc, PrevSpec,
+                                DiagID, TyName)) {
+          DS.SetRangeEnd(NameLoc);
+          Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+          TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo);
+          if (!Ty.isInvalid())
+            Type = Ty.get();
+        }
+      }
+
+      ConsumeToken(); // The identifier.
+      if (!Type) {
+        SkipUntil(tok::r_square);
+        return ExprError();
+      }
+
+      return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), Type,
+                                            ExprArg(Actions));
+    }
         
     case Action::ObjCInstanceMessage:
+      // Fall through to parse an expression.
       break;
     }
   }
@@ -1746,12 +1774,29 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
     return move(Res);
   }
 
-  return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
-                                        0, move(Res));
+  return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 0, 
+                                        move(Res));
 }
 
-/// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
-/// the rest of a message expression.
+/// \brief Parse the remainder of an Objective-C message following the
+/// '[' objc-receiver.
+///
+/// This routine handles sends to super, class messages (sent to a
+/// class name), and instance messages (sent to an object), and the
+/// target is represented by \p SuperLoc, \p ReceiverType, or \p
+/// ReceiverExpr, respectively. Only one of these parameters may have
+/// a valid value.
+///
+/// \param LBracLoc The location of the opening '['.
+///
+/// \param SuperLoc If this is a send to 'super', the location of the
+/// 'super' keyword that indicates a send to the superclass.
+///
+/// \param ReceiverType If this is a class message, the type of the
+/// class we are sending a message to.
+///
+/// \param ReceiverExpr If this is an instance message, the expression
+/// used to compute the receiver object.
 ///
 ///   objc-message-args:
 ///     objc-selector
@@ -1773,13 +1818,14 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
 ///
 Parser::OwningExprResult
 Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
-                                       SourceLocation NameLoc,
-                                       IdentifierInfo *ReceiverName,
+                                       SourceLocation SuperLoc,
+                                       TypeTy *ReceiverType,
                                        ExprArg ReceiverExpr) {
   if (Tok.is(tok::code_completion)) {
-    if (ReceiverName)
-      Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, 
-                                           0, 0);
+    if (SuperLoc.isValid())
+      Actions.CodeCompleteObjCSuperMessage(CurScope, SuperLoc, 0, 0);
+    else if (ReceiverType)
+      Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverType, 0, 0);
     else
       Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), 
                                               0, 0);
@@ -1825,8 +1871,12 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
 
       // Code completion after each argument.
       if (Tok.is(tok::code_completion)) {
-        if (ReceiverName)
-          Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc,
+        if (SuperLoc.isValid())
+          Actions.CodeCompleteObjCSuperMessage(CurScope, SuperLoc, 
+                                               KeyIdents.data(), 
+                                               KeyIdents.size());
+        else if (ReceiverType)
+          Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverType,
                                                KeyIdents.data(), 
                                                KeyIdents.size());
         else
@@ -1887,15 +1937,23 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
     KeyIdents.push_back(selIdent);
   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
 
-  // We've just parsed a keyword message.
-  if (ReceiverName)
-    return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
-                                           LBracLoc, NameLoc, SelectorLoc,
-                                           RBracLoc,
-                                           KeyExprs.take(), KeyExprs.size()));
-  return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
-                                            LBracLoc, SelectorLoc, RBracLoc,
-                                            KeyExprs.take(), KeyExprs.size()));
+  if (SuperLoc.isValid())
+    return Actions.ActOnSuperMessage(CurScope, SuperLoc, Sel,
+                                     LBracLoc, SelectorLoc, RBracLoc,
+                                     Action::MultiExprArg(Actions, 
+                                                          KeyExprs.take(),
+                                                          KeyExprs.size()));
+  else if (ReceiverType)
+    return Actions.ActOnClassMessage(CurScope, ReceiverType, Sel,
+                                     LBracLoc, SelectorLoc, RBracLoc,
+                                     Action::MultiExprArg(Actions, 
+                                                          KeyExprs.take(), 
+                                                          KeyExprs.size()));
+  return Actions.ActOnInstanceMessage(CurScope, move(ReceiverExpr), Sel,
+                                      LBracLoc, SelectorLoc, RBracLoc,
+                                      Action::MultiExprArg(Actions, 
+                                                           KeyExprs.take(), 
+                                                           KeyExprs.size()));
 }
 
 Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
index 1506d8c2dc29b1ef5ec278e1f384f53efca824f9..a7e402dfcb7bb9d0c7342d0cde03988e432e347a 100644 (file)
@@ -3872,22 +3872,47 @@ public:
                                              bool IsSuper,
                                              bool HasTrailingDot);
 
-  // ActOnClassMessage - used for both unary and keyword messages.
-  // ArgExprs is optional - if it is present, the number of expressions
-  // is obtained from NumArgs.
-  virtual ExprResult ActOnClassMessage(
-    Scope *S,
-    IdentifierInfo *receivingClassName, Selector Sel, SourceLocation lbrac,
-    SourceLocation receiverLoc, SourceLocation selectorLoc,SourceLocation rbrac,
-    ExprTy **ArgExprs, unsigned NumArgs);
-
-  // ActOnInstanceMessage - used for both unary and keyword messages.
-  // ArgExprs is optional - if it is present, the number of expressions
-  // is obtained from NumArgs.
-  virtual ExprResult ActOnInstanceMessage(
-    ExprTy *receiver, Selector Sel,
-    SourceLocation lbrac, SourceLocation receiverLoc, SourceLocation rbrac,
-    ExprTy **ArgExprs, unsigned NumArgs);
+  virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                             Selector Sel,
+                                             SourceLocation LBracLoc,
+                                             SourceLocation SelectorLoc,
+                                             SourceLocation RBracLoc,
+                                             MultiExprArg Args);
+
+  OwningExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+                                     QualType ReceiverType,
+                                     SourceLocation SuperLoc,
+                                     Selector Sel,
+                                     SourceLocation LBracLoc, 
+                                     SourceLocation SelectorLoc,
+                                     SourceLocation RBracLoc,
+                                     MultiExprArg Args);
+                                     
+  virtual OwningExprResult ActOnClassMessage(Scope *S,
+                                             TypeTy *Receiver,
+                                             Selector Sel,
+                                             SourceLocation LBracLoc, 
+                                             SourceLocation SelectorLoc,
+                                             SourceLocation RBracLoc,
+                                             MultiExprArg Args);
+  
+  OwningExprResult BuildInstanceMessage(ExprArg Receiver,
+                                        QualType ReceiverType,
+                                        SourceLocation SuperLoc,
+                                        Selector Sel,
+                                        SourceLocation LBracLoc, 
+                                        SourceLocation SelectorLoc, 
+                                        SourceLocation RBracLoc,
+                                        MultiExprArg Args);
+
+  virtual OwningExprResult ActOnInstanceMessage(Scope *S,
+                                                ExprArg Receiver,
+                                                Selector Sel,
+                                                SourceLocation LBracLoc, 
+                                                SourceLocation SelectorLoc, 
+                                                SourceLocation RBracLoc,
+                                                MultiExprArg Args);
+
 
   /// ActOnPragmaPack - Called on well formed #pragma pack(...).
   virtual void ActOnPragmaPack(PragmaPackKind Kind,
@@ -4301,8 +4326,10 @@ public:
                                               DeclPtrTy *Methods,
                                               unsigned NumMethods);
 
-  virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
-                                            SourceLocation FNameLoc,
+  virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                            IdentifierInfo **SelIdents,
+                                            unsigned NumSelIdents);
+  virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
                                             IdentifierInfo **SelIdents, 
                                             unsigned NumSelIdents);
   virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
index cb60f0aba11ea223c4e27601eac7ead34c59f18f..e71f8c84ebc524a2ecb98c2a38ef087eb17a57d8 100644 (file)
@@ -2947,62 +2947,82 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
     .Default(0);
 }
 
-void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
-                                        SourceLocation FNameLoc,
+void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
                                         IdentifierInfo **SelIdents,
                                         unsigned NumSelIdents) {
-  typedef CodeCompleteConsumer::Result Result;
   ObjCInterfaceDecl *CDecl = 0;
+  if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+    // Figure out which interface we're in.
+    CDecl = CurMethod->getClassInterface();
+    if (!CDecl)
+      return;
+    
+    // Find the superclass of this class.
+    CDecl = CDecl->getSuperClass();
+    if (!CDecl)
+      return;
 
-  if (FName->isStr("super")) {
-    // We're sending a message to "super".
-    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
-      // Figure out which interface we're in.
-      CDecl = CurMethod->getClassInterface();
-      if (!CDecl)
-        return;
-
-      // Find the superclass of this class.
-      CDecl = CDecl->getSuperClass();
-      if (!CDecl)
-        return;
+    if (CurMethod->isInstanceMethod()) {
+      // We are inside an instance method, which means that the message
+      // send [super ...] is actually calling an instance method on the
+      // current object. Build the super expression and handle this like
+      // an instance method.
+      QualType SuperTy = Context.getObjCInterfaceType(CDecl);
+      SuperTy = Context.getObjCObjectPointerType(SuperTy);
+      OwningExprResult Super
+        = Owned(new (Context) ObjCSuperExpr(SuperLoc, SuperTy));
+      return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
+                                             SelIdents, NumSelIdents);
+    }
 
-      if (CurMethod->isInstanceMethod()) {
-        // We are inside an instance method, which means that the message
-        // send [super ...] is actually calling an instance method on the
-        // current object. Build the super expression and handle this like
-        // an instance method.
-        QualType SuperTy = Context.getObjCInterfaceType(CDecl);
-        SuperTy = Context.getObjCObjectPointerType(SuperTy);
-        OwningExprResult Super
-          = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy));
-        return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
-                                               SelIdents, NumSelIdents);
-      }
+    // Fall through to send to the superclass in CDecl.
+  } else {
+    // "super" may be the name of a type or variable. Figure out which
+    // it is.
+    IdentifierInfo *Super = &Context.Idents.get("super");
+    NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, 
+                                     LookupOrdinaryName);
+    if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
+      // "super" names an interface. Use it.
+    } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
+      if (const ObjCInterfaceType *Iface
+            = Context.getTypeDeclType(TD)->getAs<ObjCInterfaceType>())
+        CDecl = Iface->getDecl();
+    } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
+      // "super" names an unresolved type; we can't be more specific.
+    } else {
+      // Assume that "super" names some kind of value and parse that way.
+      CXXScopeSpec SS;
+      UnqualifiedId id;
+      id.setIdentifier(Super, SuperLoc);
+      OwningExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
+      return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
+                                             SelIdents, NumSelIdents);
+    }
 
-      // Okay, we're calling a factory method in our superclass.
-    } 
+    // Fall through
   }
 
+  TypeTy *Receiver = 0;
+  if (CDecl)
+    Receiver = Context.getObjCInterfaceType(CDecl).getAsOpaquePtr();
+  return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, 
+                                      NumSelIdents);
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
+                                        IdentifierInfo **SelIdents,
+                                        unsigned NumSelIdents) {
+  typedef CodeCompleteConsumer::Result Result;
+  ObjCInterfaceDecl *CDecl = 0;
+
   // If the given name refers to an interface type, retrieve the
   // corresponding declaration.
-  if (!CDecl)
-    if (TypeTy *Ty = getTypeName(*FName, FNameLoc, S, 0, false)) {
-      QualType T = GetTypeFromParser(Ty, 0);
-      if (!T.isNull()) 
-        if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
-          CDecl = Interface->getDecl();
-    }
-
-  if (!CDecl && FName->isStr("super")) {
-    // "super" may be the name of a variable, in which case we are
-    // probably calling an instance method.
-    CXXScopeSpec SS;
-    UnqualifiedId id;
-    id.setIdentifier(FName, FNameLoc);
-    OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false);
-    return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
-                                           SelIdents, NumSelIdents);
+  if (Receiver) {
+    QualType T = GetTypeFromParser(Receiver, 0);
+    if (!T.isNull()) 
+      if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
+        CDecl = Interface->getDecl();
   }
 
   // Add all of the factory methods in this Objective-C class, its protocols,
@@ -3013,7 +3033,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
   if (CDecl) 
     AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext, 
                    Results);  
-  else if (FName->isStr("id")) {
+  else {
     // We're messaging "id" as a type; provide all class/factory methods.
 
     // If we have an external source, load the entire class method
index 6be1e1923ad32981e9f2130d992d3cd81c029cbb..d28410085958e27d2ad1fdd55959f4d139b51419 100644 (file)
@@ -16,6 +16,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
 #include "llvm/ADT/SmallString.h"
 #include "clang/Lex/Preprocessor.h"
 
@@ -186,7 +187,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
     return false;
   }
 
-  ReturnType = Method->getResultType();
+  ReturnType = Method->getResultType().getNonReferenceType();
 
   unsigned NumNamedArgs = Sel.getNumArgs();
   // Method might have more arguments than selector indicates. This is due
@@ -245,6 +246,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
     }
   }
 
+  DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
   return IsError;
 }
 
@@ -585,153 +587,274 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
   return ObjCInstanceMessage;
 }
 
-// ActOnClassMessage - used for both unary and keyword messages.
-// ArgExprs is optional - if it is present, the number of expressions
-// is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::
-ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel,
-                  SourceLocation lbrac, SourceLocation receiverLoc,
-                  SourceLocation selectorLoc, SourceLocation rbrac,
-                  ExprTy **Args, unsigned NumArgs) {
-  assert(receiverName && "missing receiver class name");
-
-  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
-  ObjCInterfaceDecl *ClassDecl = 0;
-  bool isSuper = false;
-
-  // Special case a message to super, which can be either a class message or an
-  // instance message, depending on what CurMethodDecl is.
-  if (receiverName->isStr("super")) {
-    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
-      ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
-      if (!OID)
-        return Diag(lbrac, diag::error_no_super_class_message)
-                      << CurMethod->getDeclName();
-      ClassDecl = OID->getSuperClass();
-      if (ClassDecl == 0)
-        return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
-      if (CurMethod->isInstanceMethod()) {
-        QualType superTy = Context.getObjCInterfaceType(ClassDecl);
-        superTy = Context.getObjCObjectPointerType(superTy);
-        ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
-                                                              superTy);
-        // We are really in an instance method, redirect.
-        return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
-                                    selectorLoc, rbrac, Args, NumArgs);
-      }
-      
-      // Otherwise, if this is a class method, try dispatching to our
-      // superclass, which is in ClassDecl.
-      isSuper = true;
+Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S, 
+                                               SourceLocation SuperLoc,
+                                               Selector Sel,
+                                               SourceLocation LBracLoc,
+                                               SourceLocation SelectorLoc,
+                                               SourceLocation RBracLoc,
+                                               MultiExprArg Args) {
+  // Determine whether we are inside a method or not.
+  ObjCMethodDecl *Method = getCurMethodDecl();
+  if (Method) {
+    ObjCInterfaceDecl *Class = Method->getClassInterface();
+    if (!Class) {
+      Diag(SuperLoc, diag::error_no_super_class_message)
+        << Method->getDeclName();
+      return ExprError();
     }
+
+    if (ObjCInterfaceDecl *Super = Class->getSuperClass()) {
+      // We are in a method whose class has a superclass, so 'super'
+      // is acting as a keyword.
+      if (Method->isInstanceMethod()) {
+        // Since we are in an instance method, this is an instance
+        // message to the superclass instance.
+        QualType SuperTy = Context.getObjCInterfaceType(Super);
+        SuperTy = Context.getObjCObjectPointerType(SuperTy);
+        return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc,
+                                    Sel, LBracLoc, SelectorLoc, RBracLoc,
+                                    move(Args));
+      }
+
+      // Since we are in a class method, this is a class message to
+      // the superclass.
+      return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+                               Context.getObjCInterfaceType(Super),
+                               SuperLoc, Sel, LBracLoc, SelectorLoc,
+                               RBracLoc, move(Args));
+    } 
+
+    // The current class does not have a superclass.
+    Diag(SuperLoc, diag::error_no_super_class) << Class->getIdentifier();
+    return ExprError();
   }
+
+  Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
+  return ExprError();
+    
+#if 0
+  // We are not inside a method, or the method is in a class that has
+  // no superclass, so perform normal name lookup on "super".
+  IdentifierInfo &SuperId = Context.Idents.get("super");
+  NamedDecl *Super = LookupSingleName(S, &SuperId, SuperLoc,
+                                      LookupOrdinaryName);
+  if (!Super) {
+    Diag(SuperLoc, diag::err_undeclared_var_use) << &SuperId;
+    return ExprError();
+  }
+
+  if (isa<TypeDecl>(Super) || isa<ObjCInterfaceDecl>(Super)) {
+    // Name lookup found a type named 'super'; create a class message
+    // sending to it.
+    QualType SuperType = 
+      isa<TypeDecl>(Super)? Context.getTypeDeclType(cast<TypeDecl>(Super))
+               : Context.getObjCInterfaceType(cast<ObjCInterfaceDecl>(Super));
+    TypeSourceInfo *SuperTypeInfo
+      = Context.getTrivialTypeSourceInfo(SuperType, SuperLoc);
+    return BuildClassMessage(SuperTypeInfo, SuperType, 
+                             /*SuperLoc=*/SourceLocation(),
+                             Sel, LBracLoc, SelectorLoc, RBracLoc,
+                             move(Args));
+  }
+
+  // Assume that "super" is the name of a value of some
+  // sort. Type-check it as an id-expression.
+  CXXScopeSpec SS;
+  UnqualifiedId Id;
+  Id.setIdentifier(&SuperId, SuperLoc);
+  OwningExprResult Receiver = ActOnIdExpression(S, SS, Id, false, false);
+  if (Receiver.isInvalid() || !Receiver.get())
+    return ExprError();
+
+  Expr *ReceiverExpr = static_cast<Expr *>(Receiver.get());
+  return BuildInstanceMessage(move(Receiver), ReceiverExpr->getType(),
+                              /*SuperLoc=*/SourceLocation(),
+                              Sel, LBracLoc, SelectorLoc, RBracLoc,
+                              move(Args));
+#endif
+}
+
+/// \brief Build an Objective-C class message expression.
+///
+/// This routine takes care of both normal class messages and
+/// class messages to the superclass.
+///
+/// \param ReceiverTypeInfo Type source information that describes the
+/// receiver of this message. This may be NULL, in which case we are
+/// sending to the superclass and \p SuperLoc must be a valid source
+/// location.
+
+/// \param ReceiverType The type of the object receiving the
+/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
+/// type as that refers to. For a superclass send, this is the type of
+/// the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param SelectorLoc The location of the first identifier in the selector.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+                                               QualType ReceiverType,
+                                               SourceLocation SuperLoc,
+                                               Selector Sel,
+                                               SourceLocation LBracLoc, 
+                                               SourceLocation SelectorLoc,
+                                               SourceLocation RBracLoc,
+                                               MultiExprArg ArgsIn) {
+  assert(!ReceiverType->isDependentType() && 
+         "Dependent class messages not yet implemented");
   
-  if (ClassDecl == 0)
-    ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc, true);
-
-  // The following code allows for the following GCC-ism:
-  //
-  //  typedef XCElementDisplayRect XCElementGraphicsRect;
-  //
-  //  @implementation XCRASlice
-  //  - whatever { // Note that XCElementGraphicsRect is a typedef name.
-  //    _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
-  //  }
-  //
-  // If necessary, the following lookup could move to getObjCInterfaceDecl().
-  if (!ClassDecl) {
-    NamedDecl *IDecl
-      = LookupSingleName(TUScope, receiverName, receiverLoc, 
-                         LookupOrdinaryName);
-    if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl))
-      if (const ObjCInterfaceType *OCIT
-                      = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>())
-        ClassDecl = OCIT->getDecl();
-
-    if (!ClassDecl) {
-      // Give a better error message for invalid use of super.
-      if (receiverName->isStr("super"))
-        Diag(receiverLoc, diag::err_invalid_receiver_to_message_super);
-      else
-        Diag(receiverLoc, diag::err_invalid_receiver_to_message);
-      return true;
-    }
+  SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+             : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
+
+  // Find the class to which we are sending this message.
+  ObjCInterfaceDecl *Class = 0;
+  if (const ObjCInterfaceType *ClassType
+                                 = ReceiverType->getAs<ObjCInterfaceType>())
+    Class = ClassType->getDecl();
+  else {
+    Diag(Loc, diag::err_invalid_receiver_class_message)
+      << ReceiverType;
+    return ExprError();
   }
-  assert(ClassDecl && "missing interface declaration");
+  assert(Class && "We don't know which class we're messaging?");
+
+  // Find the method we are messaging.
   ObjCMethodDecl *Method = 0;
-  QualType returnType;
-  if (ClassDecl->isForwardDecl()) {
-    // A forward class used in messaging is tread as a 'Class'
-    Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
-    Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+  if (Class->isForwardDecl()) {
+    // A forward class used in messaging is treated as a 'Class'
+    Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
+    Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                             SourceRange(LBracLoc, RBracLoc));
     if (Method)
       Diag(Method->getLocation(), diag::note_method_sent_forward_class)
         << Method->getDeclName();
   }
   if (!Method)
-    Method = ClassDecl->lookupClassMethod(Sel);
+    Method = Class->lookupClassMethod(Sel);
 
   // If we have an implementation in scope, check "private" methods.
   if (!Method)
-    Method = LookupPrivateClassMethod(Sel, ClassDecl);
+    Method = LookupPrivateClassMethod(Sel, Class);
 
-  if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
-    return true;
+  if (Method && DiagnoseUseOfDecl(Method, Loc))
+    return ExprError();
 
-  if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
-                                lbrac, rbrac, returnType))
-    return true;
+  // Check the argument types and determine the result type.
+  QualType ReturnType;
+  unsigned NumArgs = ArgsIn.size();
+  Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+  if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true,
+                                LBracLoc, RBracLoc, ReturnType)) {
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I]->Destroy(Context);
+    return ExprError();
+  }
 
-  returnType = returnType.getNonReferenceType();
+  // Construct the appropriate ObjCMessageExpr.
+  if (SuperLoc.isValid())
+    return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, 
+                                         SuperLoc, /*IsInstanceSuper=*/false, 
+                                         ReceiverType, Sel, Method, Args, 
+                                         NumArgs, RBracLoc));
 
-  QualType ReceiverType = Context.getObjCInterfaceType(ClassDecl);
-  if (isSuper)
-    return ObjCMessageExpr::Create(Context, returnType, lbrac, receiverLoc,
-                                   /*IsInstanceSuper=*/false,ReceiverType, 
-                                   Sel, Method, ArgExprs, NumArgs, rbrac);
-  
-  // If we have the ObjCInterfaceDecl* for the class that is receiving the
-  // message, use that to construct the ObjCMessageExpr.  Otherwise pass on the
-  // IdentifierInfo* for the class.
-  TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(ReceiverType,
-                                                            receiverLoc);
-  return ObjCMessageExpr::Create(Context, returnType, lbrac, TSInfo, Sel, 
-                                 Method, ArgExprs, NumArgs, rbrac);
+  return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, 
+                                       ReceiverTypeInfo, Sel, Method, Args, 
+                                       NumArgs, RBracLoc));
 }
 
-// ActOnInstanceMessage - used for both unary and keyword messages.
+// ActOnClassMessage - used for both unary and keyword messages.
 // ArgExprs is optional - if it is present, the number of expressions
 // is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
-                                            SourceLocation lbrac,
-                                            SourceLocation receiverLoc,
-                                            SourceLocation rbrac,
-                                            ExprTy **Args, unsigned NumArgs) {
-  assert(receiver && "missing receiver expression");
+Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S, 
+                                               TypeTy *Receiver,
+                                               Selector Sel,
+                                               SourceLocation LBracLoc,
+                                               SourceLocation SelectorLoc,
+                                               SourceLocation RBracLoc,
+                                               MultiExprArg Args) {
+  TypeSourceInfo *ReceiverTypeInfo;
+  QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
+  if (ReceiverType.isNull())
+    return ExprError();
 
-  Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
-  Expr *RExpr = static_cast<Expr *>(receiver);
 
-  // If necessary, apply function/array conversion to the receiver.
-  // C99 6.7.5.3p[7,8].
-  DefaultFunctionArrayLvalueConversion(RExpr);
+  if (!ReceiverTypeInfo)
+    ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
 
-  ObjCMethodDecl *Method = 0;
-  QualType returnType;
-  QualType ReceiverCType =
-    Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
+  return BuildClassMessage(ReceiverTypeInfo, ReceiverType, 
+                           /*SuperLoc=*/SourceLocation(), Sel, 
+                           LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
 
-  // Handle messages to id.
-  if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
-      Context.isObjCNSObjectType(RExpr->getType())) {
-    // FIXME: If our superclass is NSObject and we message 'super',
-    // we'll end up looking in the global method pool??
+/// \brief Build an Objective-C instance message expression.
+///
+/// This routine takes care of both normal instance messages and
+/// instance messages to the superclass instance.
+///
+/// \param Receiver The expression that computes the object that will
+/// receive this message. This may be empty, in which case we are
+/// sending to the superclass instance and \p SuperLoc must be a valid
+/// source location.
+///
+/// \param ReceiverType The (static) type of the object receiving the
+/// message. When a \p Receiver expression is provided, this is the
+/// same type as that expression. For a superclass instance send, this
+/// is a pointer to the type of the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass instance message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param SelectorLoc The location of the first identifier in the selector.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
+                                                  QualType ReceiverType,
+                                                  SourceLocation SuperLoc,
+                                                  Selector Sel,
+                                                  SourceLocation LBracLoc, 
+                                                  SourceLocation SelectorLoc, 
+                                                  SourceLocation RBracLoc,
+                                                  MultiExprArg ArgsIn) {
+  // If we have a receiver expression, perform appropriate promotions
+  // and determine receiver type.
+  Expr *Receiver = ReceiverE.takeAs<Expr>();
+  if (Receiver) {
+    // If necessary, apply function/array conversion to the receiver.
+    // C99 6.7.5.3p[7,8].
+    DefaultFunctionArrayLvalueConversion(Receiver);
+    ReceiverType = Receiver->getType();
+  }
 
-    Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+  // The location of the receiver.
+  SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+
+  ObjCMethodDecl *Method = 0;
+  // Handle messages to id.
+  if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
+      (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+    Method = LookupInstanceMethodInGlobalPool(Sel, 
+                                              SourceRange(LBracLoc, RBracLoc));
     if (!Method)
-      Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
-  } else if (ReceiverCType->isObjCClassType() ||
-             ReceiverCType->isObjCQualifiedClassType()) {
+      Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                               SourceRange(LBracLoc, RBracLoc));
+  } else if (ReceiverType->isObjCClassType() ||
+             ReceiverType->isObjCQualifiedClassType()) {
     // Handle messages to Class.
     if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
@@ -744,24 +867,25 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
         // FIXME: if we still haven't found a method, we need to look in
         // protocols (if we have qualifiers).
       }
-      if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
-        return true;
+      if (Method && DiagnoseUseOfDecl(Method, Loc))
+        return ExprError();
     }
     if (!Method) {
       // If not messaging 'self', look for any factory method named 'Sel'.
-      if (!isSelfExpr(RExpr)) {
-        Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+      if (!Receiver || !isSelfExpr(Receiver)) {
+        Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                             SourceRange(LBracLoc, RBracLoc));
         if (!Method) {
           // If no class (factory) method was found, check if an _instance_
           // method of the same name exists in the root class only.
-          Method = LookupInstanceMethodInGlobalPool(
-                                   Sel, SourceRange(lbrac,rbrac));
+          Method = LookupInstanceMethodInGlobalPool(Sel,
+                                             SourceRange(LBracLoc, RBracLoc));
           if (Method)
               if (const ObjCInterfaceDecl *ID =
                 dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
               if (ID->getSuperClass())
-                Diag(lbrac, diag::warn_root_inst_method_not_found)
-                  << Sel << SourceRange(lbrac, rbrac);
+                Diag(Loc, diag::warn_root_inst_method_not_found)
+                  << Sel << SourceRange(LBracLoc, RBracLoc);
             }
         }
       }
@@ -771,8 +895,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
 
     // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
     // long as one of the protocols implements the selector (if not, warn).
-    if (const ObjCObjectPointerType *QIdTy =
-        ReceiverCType->getAsObjCQualifiedIdType()) {
+    if (const ObjCObjectPointerType *QIdTy 
+                                 = ReceiverType->getAsObjCQualifiedIdType()) {
       // Search protocols for instance methods.
       for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
              E = QIdTy->qual_end(); I != E; ++I) {
@@ -783,10 +907,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
         if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
           break;
       }
-    } else if (const ObjCObjectPointerType *OCIType =
-               ReceiverCType->getAsObjCInterfacePointerType()) {
+    } else if (const ObjCObjectPointerType *OCIType
+                 = ReceiverType->getAsObjCInterfacePointerType()) {
       // We allow sending a message to a pointer to an interface (an object).
-
       ClassDecl = OCIType->getInterfaceDecl();
       // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
       // faster than the following method (which can do *many* linear searches).
@@ -805,56 +928,80 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
         // If we have implementations in scope, check "private" methods.
         Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
 
-        if (!Method && !isSelfExpr(RExpr)) {
+        if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
           // If we still haven't found a method, look in the global pool. This
           // behavior isn't very desirable, however we need it for GCC
           // compatibility. FIXME: should we deviate??
           if (OCIType->qual_empty()) {
-            Method = LookupInstanceMethodInGlobalPool(
-                                                Sel, SourceRange(lbrac,rbrac));
+            Method = LookupInstanceMethodInGlobalPool(Sel,
+                                               SourceRange(LBracLoc, RBracLoc));
             if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
-              Diag(lbrac, diag::warn_maynot_respond)
+              Diag(Loc, diag::warn_maynot_respond)
                 << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
           }
         }
       }
-      if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
-        return true;
+      if (Method && DiagnoseUseOfDecl(Method, Loc))
+        return ExprError();
     } else if (!Context.getObjCIdType().isNull() &&
-               (ReceiverCType->isPointerType() ||
-                (ReceiverCType->isIntegerType() &&
-                 ReceiverCType->isScalarType()))) {
+               (ReceiverType->isPointerType() ||
+                (ReceiverType->isIntegerType() &&
+                 ReceiverType->isScalarType()))) {
       // Implicitly convert integers and pointers to 'id' but emit a warning.
-      Diag(lbrac, diag::warn_bad_receiver_type)
-        << RExpr->getType() << RExpr->getSourceRange();
-      if (ReceiverCType->isPointerType())
-        ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast);
+      Diag(Loc, diag::warn_bad_receiver_type)
+        << ReceiverType 
+        << Receiver->getSourceRange();
+      if (ReceiverType->isPointerType())
+        ImpCastExprToType(Receiver, Context.getObjCIdType(), 
+                          CastExpr::CK_BitCast);
       else
-        ImpCastExprToType(RExpr, Context.getObjCIdType(),
+        ImpCastExprToType(Receiver, Context.getObjCIdType(),
                           CastExpr::CK_IntegralToPointer);
+      ReceiverType = Receiver->getType();
     } else {
       // Reject other random receiver types (e.g. structs).
-      Diag(lbrac, diag::err_bad_receiver_type)
-        << RExpr->getType() << RExpr->getSourceRange();
-      return true;
+      Diag(Loc, diag::err_bad_receiver_type)
+        << ReceiverType << Receiver->getSourceRange();
+      return ExprError();
     }
   }
 
-  if (Method)
-    DiagnoseSentinelCalls(Method, receiverLoc, ArgExprs, NumArgs);
-  if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
-                                lbrac, rbrac, returnType))
-    return true;
-  returnType = returnType.getNonReferenceType();
+  // Check the message arguments.
+  unsigned NumArgs = ArgsIn.size();
+  Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+  QualType ReturnType;
+  if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false,
+                                LBracLoc, RBracLoc, ReturnType))
+    return ExprError();
 
-  if (isa<ObjCSuperExpr>(RExpr))
-    return ObjCMessageExpr::Create(Context, returnType, lbrac,
-                                   RExpr->getLocStart(), 
-                                   /*IsInstanceSuper=*/true,
-                                   RExpr->getType(),
-                                   Sel, Method, ArgExprs, NumArgs, rbrac);
+  // Construct the appropriate ObjCMessageExpr instance.
+  if (SuperLoc.isValid())
+    return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc,
+                                         SuperLoc,  /*IsInstanceSuper=*/true,
+                                         ReceiverType, Sel, Method, 
+                                         Args, NumArgs, RBracLoc));
+
+  return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, Receiver, 
+                                       Sel, Method, Args, NumArgs, RBracLoc));
+}
+
+// ActOnInstanceMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+Sema::OwningExprResult Sema::ActOnInstanceMessage(Scope *S,
+                                                  ExprArg ReceiverE, 
+                                                  Selector Sel,
+                                                  SourceLocation LBracLoc,
+                                                  SourceLocation SelectorLoc,
+                                                  SourceLocation RBracLoc,
+                                                  MultiExprArg Args) {
+  Expr *Receiver = static_cast<Expr *>(ReceiverE.get());
+  if (!Receiver)
+    return ExprError();
 
-  return ObjCMessageExpr::Create(Context, returnType, lbrac, RExpr, Sel,
-                                 Method, ArgExprs, NumArgs, rbrac);
+  return BuildInstanceMessage(move(ReceiverE), Receiver->getType(),
+                              /*SuperLoc=*/SourceLocation(),
+                              Sel, LBracLoc, SelectorLoc, RBracLoc,
+                              move(Args));
 }
 
index 16f0155173d06ab83ea9f7d3be5a666f32fe9a4d..1174dd2e1706da32651d5e010a481d9d8412fd39 100644 (file)
@@ -5,5 +5,5 @@ typedef struct NotAClass {
 } NotAClass;
 
 void foo() {
-  [NotAClass nonexistent_method]; // expected-error {{invalid receiver to message expression}}
+  [NotAClass nonexistent_method]; // expected-error {{receiver type 'NotAClass' (aka 'struct NotAClass') is not an Objective-C class}}
 }
index 9498a8ce7ea9ada140986518c9b27d300d927546..31d8db1702549b422e45327455a540e0f80de64b 100644 (file)
@@ -85,5 +85,3 @@ int test3() {
   id X[] = { [ super superClassMethod] };
   return 0;
 }
-
-
index 93a600aef32e937dcb8aaa47a35a55fa4d3dd229..0d5bef8bb7a7d0376b20616215ceb8dc27b6863d 100644 (file)
@@ -6,7 +6,7 @@
 @implementation I1
 - (void)method {
   struct x { };
-  [x method]; // expected-error{{invalid receiver to message expression}}
+  [x method]; // expected-error{{receiver type 'x' is not an Objective-C class}}
 }
 @end
 
@@ -24,6 +24,6 @@ typedef struct { int x; } ivar;
   [ivar method];
 }
 + (void)method {
-  [ivar method]; // expected-error{{invalid receiver to message expression}}
+  [ivar method]; // expected-error{{receiver type 'ivar' (aka 'ivar') is not an Objective-C class}}
 }
 @end