[cfe-commits] r102021 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Wed Apr 21 12:57:20 PDT 2010


Author: dgregor
Date: Wed Apr 21 14:57:20 2010
New Revision: 102021

URL: http://llvm.org/viewvc/llvm-project?rev=102021&view=rev
Log:
Rework the Parser-Sema interaction for Objective-C message
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.


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

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Wed Apr 21 14:57:20 2010
@@ -343,6 +343,29 @@
   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 @@
                   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 @@
 
 /// 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:

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 21 14:57:20 2010
@@ -2046,6 +2046,8 @@
   "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'">;

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Apr 21 14:57:20 2010
@@ -2389,29 +2389,63 @@
                                              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 @@
                                               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.

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Apr 21 14:57:20 2010
@@ -1005,12 +1005,12 @@
   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.

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Apr 21 14:57:20 2010
@@ -268,11 +268,11 @@
 /// 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 @@
 /// [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 @@
 ///
 ///       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

Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Wed Apr 21 14:57:20 2010
@@ -129,13 +129,16 @@
     // 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 @@
         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;
       }
     }
 

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Wed Apr 21 14:57:20 2010
@@ -1714,7 +1714,7 @@
 ///   objc-message-expr:
 ///     '[' objc-receiver objc-message-args ']'
 ///
-///   objc-receiver:
+///   objc-receiver: [C]
 ///     'super'
 ///     expression
 ///     class-name
@@ -1730,11 +1730,39 @@
                                        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 @@
     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::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 @@
 
       // 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 @@
     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) {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Apr 21 14:57:20 2010
@@ -3872,22 +3872,47 @@
                                              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 @@
                                               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,

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Apr 21 14:57:20 2010
@@ -2947,62 +2947,82 @@
     .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 (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);
+    }
+
+    // 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);
+    }
 
-  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(FNameLoc, SuperTy));
-        return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.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 @@
   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

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Apr 21 14:57:20 2010
@@ -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 @@
     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 @@
     }
   }
 
+  DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
   return IsError;
 }
 
@@ -585,153 +587,274 @@
   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);
+  SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+             : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
 
-  // 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;
-    }
+  // 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 (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
-                                lbrac, rbrac, returnType))
-    return true;
+  if (Method && DiagnoseUseOfDecl(Method, Loc))
+    return ExprError();
 
-  returnType = returnType.getNonReferenceType();
+  // 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();
+  }
 
-  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);
+  // Construct the appropriate ObjCMessageExpr.
+  if (SuperLoc.isValid())
+    return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, 
+                                         SuperLoc, /*IsInstanceSuper=*/false, 
+                                         ReceiverType, Sel, Method, Args, 
+                                         NumArgs, RBracLoc));
+
+  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");
-
-  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);
+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();
 
-  ObjCMethodDecl *Method = 0;
-  QualType returnType;
-  QualType ReceiverCType =
-    Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
 
-  // 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??
+  if (!ReceiverTypeInfo)
+    ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
 
-    Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+  return BuildClassMessage(ReceiverTypeInfo, ReceiverType, 
+                           /*SuperLoc=*/SourceLocation(), Sel, 
+                           LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
+
+/// \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();
+  }
+
+  // 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 @@
         // 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 @@
 
     // 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 @@
         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 @@
         // 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));
 }
 

Modified: cfe/trunk/test/SemaObjC/invalid-receiver.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/invalid-receiver.m?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/invalid-receiver.m (original)
+++ cfe/trunk/test/SemaObjC/invalid-receiver.m Wed Apr 21 14:57:20 2010
@@ -5,5 +5,5 @@
 } 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}}
 }

Modified: cfe/trunk/test/SemaObjC/super.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/super.m?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/super.m (original)
+++ cfe/trunk/test/SemaObjC/super.m Wed Apr 21 14:57:20 2010
@@ -85,5 +85,3 @@
   id X[] = { [ super superClassMethod] };
   return 0;
 }
-
-

Modified: cfe/trunk/test/SemaObjCXX/message.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/message.mm?rev=102021&r1=102020&r2=102021&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/message.mm (original)
+++ cfe/trunk/test/SemaObjCXX/message.mm Wed Apr 21 14:57:20 2010
@@ -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 @@
   [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





More information about the cfe-commits mailing list