diff options
-rw-r--r-- | include/clang/AST/ExprObjC.h | 28 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 106 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 8 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 18 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 104 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 63 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 114 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 477 | ||||
-rw-r--r-- | test/SemaObjC/invalid-receiver.m | 2 | ||||
-rw-r--r-- | test/SemaObjC/super.m | 2 | ||||
-rw-r--r-- | test/SemaObjCXX/message.mm | 4 |
13 files changed, 674 insertions, 309 deletions
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 7aed6cabef..04b2c20b85 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -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: diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7919d8247a..a5be82df86 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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'">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 65a8769b9b..66ef8d0c67 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 7e366c4d27..8d98f60550 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 27696c438f..ef35dcb3f6 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -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 diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 123908d25a..b0735b3cab 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -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; } } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 057907d112..56937a66cd 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1506d8c2dc..a7e402dfcb 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index cb60f0aba1..e71f8c84eb 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -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 diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 6be1e1923a..d284100859 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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 exp |