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.
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));
/// 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:
"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'">;
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,
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.
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.
/// 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));
/// [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]
///
/// 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
// 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!
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;
}
}
/// objc-message-expr:
/// '[' objc-receiver objc-message-args ']'
///
-/// objc-receiver:
+/// objc-receiver: [C]
/// 'super'
/// expression
/// class-name
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;
}
}
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
///
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);
// 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
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) {
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,
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,
.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,
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
#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"
return false;
}
- ReturnType = Method->getResultType();
+ ReturnType = Method->getResultType().getNonReferenceType();
unsigned NumNamedArgs = Sel.getNumArgs();
// Method might have more arguments than selector indicates. This is due
}
}
+ DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
return IsError;
}
return ObjCInstanceMessage;
}
-// ActOnClassMessage - used for both unary and keyword messages.
-// ArgExprs is optional - if it is present, the number of expressions
-// is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::
-ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel,
- SourceLocation lbrac, SourceLocation receiverLoc,
- SourceLocation selectorLoc, SourceLocation rbrac,
- ExprTy **Args, unsigned NumArgs) {
- assert(receiverName && "missing receiver class name");
-
- Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
- ObjCInterfaceDecl *ClassDecl = 0;
- bool isSuper = false;
-
- // Special case a message to super, which can be either a class message or an
- // instance message, depending on what CurMethodDecl is.
- if (receiverName->isStr("super")) {
- if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
- ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
- if (!OID)
- return Diag(lbrac, diag::error_no_super_class_message)
- << CurMethod->getDeclName();
- ClassDecl = OID->getSuperClass();
- if (ClassDecl == 0)
- return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
- if (CurMethod->isInstanceMethod()) {
- QualType superTy = Context.getObjCInterfaceType(ClassDecl);
- superTy = Context.getObjCObjectPointerType(superTy);
- ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
- superTy);
- // We are really in an instance method, redirect.
- return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
- selectorLoc, rbrac, Args, NumArgs);
- }
-
- // Otherwise, if this is a class method, try dispatching to our
- // superclass, which is in ClassDecl.
- isSuper = true;
+Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
+ // Determine whether we are inside a method or not.
+ ObjCMethodDecl *Method = getCurMethodDecl();
+ if (Method) {
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ if (!Class) {
+ Diag(SuperLoc, diag::error_no_super_class_message)
+ << Method->getDeclName();
+ return ExprError();
}
+
+ if (ObjCInterfaceDecl *Super = Class->getSuperClass()) {
+ // We are in a method whose class has a superclass, so 'super'
+ // is acting as a keyword.
+ if (Method->isInstanceMethod()) {
+ // Since we are in an instance method, this is an instance
+ // message to the superclass instance.
+ QualType SuperTy = Context.getObjCInterfaceType(Super);
+ SuperTy = Context.getObjCObjectPointerType(SuperTy);
+ return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc,
+ Sel, LBracLoc, SelectorLoc, RBracLoc,
+ move(Args));
+ }
+
+ // Since we are in a class method, this is a class message to
+ // the superclass.
+ return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+ Context.getObjCInterfaceType(Super),
+ SuperLoc, Sel, LBracLoc, SelectorLoc,
+ RBracLoc, move(Args));
+ }
+
+ // The current class does not have a superclass.
+ Diag(SuperLoc, diag::error_no_super_class) << Class->getIdentifier();
+ return ExprError();
}
+
+ Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
+ return ExprError();
+
+#if 0
+ // We are not inside a method, or the method is in a class that has
+ // no superclass, so perform normal name lookup on "super".
+ IdentifierInfo &SuperId = Context.Idents.get("super");
+ NamedDecl *Super = LookupSingleName(S, &SuperId, SuperLoc,
+ LookupOrdinaryName);
+ if (!Super) {
+ Diag(SuperLoc, diag::err_undeclared_var_use) << &SuperId;
+ return ExprError();
+ }
+
+ if (isa<TypeDecl>(Super) || isa<ObjCInterfaceDecl>(Super)) {
+ // Name lookup found a type named 'super'; create a class message
+ // sending to it.
+ QualType SuperType =
+ isa<TypeDecl>(Super)? Context.getTypeDeclType(cast<TypeDecl>(Super))
+ : Context.getObjCInterfaceType(cast<ObjCInterfaceDecl>(Super));
+ TypeSourceInfo *SuperTypeInfo
+ = Context.getTrivialTypeSourceInfo(SuperType, SuperLoc);
+ return BuildClassMessage(SuperTypeInfo, SuperType,
+ /*SuperLoc=*/SourceLocation(),
+ Sel, LBracLoc, SelectorLoc, RBracLoc,
+ move(Args));
+ }
+
+ // Assume that "super" is the name of a value of some
+ // sort. Type-check it as an id-expression.
+ CXXScopeSpec SS;
+ UnqualifiedId Id;
+ Id.setIdentifier(&SuperId, SuperLoc);
+ OwningExprResult Receiver = ActOnIdExpression(S, SS, Id, false, false);
+ if (Receiver.isInvalid() || !Receiver.get())
+ return ExprError();
+
+ Expr *ReceiverExpr = static_cast<Expr *>(Receiver.get());
+ return BuildInstanceMessage(move(Receiver), ReceiverExpr->getType(),
+ /*SuperLoc=*/SourceLocation(),
+ Sel, LBracLoc, SelectorLoc, RBracLoc,
+ move(Args));
+#endif
+}
+
+/// \brief Build an Objective-C class message expression.
+///
+/// This routine takes care of both normal class messages and
+/// class messages to the superclass.
+///
+/// \param ReceiverTypeInfo Type source information that describes the
+/// receiver of this message. This may be NULL, in which case we are
+/// sending to the superclass and \p SuperLoc must be a valid source
+/// location.
+
+/// \param ReceiverType The type of the object receiving the
+/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
+/// type as that refers to. For a superclass send, this is the type of
+/// the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param SelectorLoc The location of the first identifier in the selector.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg ArgsIn) {
+ assert(!ReceiverType->isDependentType() &&
+ "Dependent class messages not yet implemented");
- if (ClassDecl == 0)
- ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc, true);
-
- // The following code allows for the following GCC-ism:
- //
- // typedef XCElementDisplayRect XCElementGraphicsRect;
- //
- // @implementation XCRASlice
- // - whatever { // Note that XCElementGraphicsRect is a typedef name.
- // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
- // }
- //
- // If necessary, the following lookup could move to getObjCInterfaceDecl().
- if (!ClassDecl) {
- NamedDecl *IDecl
- = LookupSingleName(TUScope, receiverName, receiverLoc,
- LookupOrdinaryName);
- if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl))
- if (const ObjCInterfaceType *OCIT
- = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>())
- ClassDecl = OCIT->getDecl();
-
- if (!ClassDecl) {
- // Give a better error message for invalid use of super.
- if (receiverName->isStr("super"))
- Diag(receiverLoc, diag::err_invalid_receiver_to_message_super);
- else
- Diag(receiverLoc, diag::err_invalid_receiver_to_message);
- return true;
- }
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+ : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
+
+ // Find the class to which we are sending this message.
+ ObjCInterfaceDecl *Class = 0;
+ if (const ObjCInterfaceType *ClassType
+ = ReceiverType->getAs<ObjCInterfaceType>())
+ Class = ClassType->getDecl();
+ else {
+ Diag(Loc, diag::err_invalid_receiver_class_message)
+ << ReceiverType;
+ return ExprError();
}
- assert(ClassDecl && "missing interface declaration");
+ assert(Class && "We don't know which class we're messaging?");
+
+ // Find the method we are messaging.
ObjCMethodDecl *Method = 0;
- QualType returnType;
- if (ClassDecl->isForwardDecl()) {
- // A forward class used in messaging is tread as a 'Class'
- Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
- Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+ if (Class->isForwardDecl()) {
+ // A forward class used in messaging is treated as a 'Class'
+ Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
if (Method)
Diag(Method->getLocation(), diag::note_method_sent_forward_class)
<< Method->getDeclName();
}
if (!Method)
- Method = ClassDecl->lookupClassMethod(Sel);
+ Method = Class->lookupClassMethod(Sel);
// If we have an implementation in scope, check "private" methods.
if (!Method)
- Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ Method = LookupPrivateClassMethod(Sel, Class);
- if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
- return true;
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
- if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
- lbrac, rbrac, returnType))
- return true;
+ // Check the argument types and determine the result type.
+ QualType ReturnType;
+ unsigned NumArgs = ArgsIn.size();
+ Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+ if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true,
+ LBracLoc, RBracLoc, ReturnType)) {
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Destroy(Context);
+ return ExprError();
+ }
- returnType = returnType.getNonReferenceType();
+ // Construct the appropriate ObjCMessageExpr.
+ if (SuperLoc.isValid())
+ return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc,
+ SuperLoc, /*IsInstanceSuper=*/false,
+ ReceiverType, Sel, Method, Args,
+ NumArgs, RBracLoc));
- QualType ReceiverType = Context.getObjCInterfaceType(ClassDecl);
- if (isSuper)
- return ObjCMessageExpr::Create(Context, returnType, lbrac, receiverLoc,
- /*IsInstanceSuper=*/false,ReceiverType,
- Sel, Method, ArgExprs, NumArgs, rbrac);
-
- // If we have the ObjCInterfaceDecl* for the class that is receiving the
- // message, use that to construct the ObjCMessageExpr. Otherwise pass on the
- // IdentifierInfo* for the class.
- TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(ReceiverType,
- receiverLoc);
- return ObjCMessageExpr::Create(Context, returnType, lbrac, TSInfo, Sel,
- Method, ArgExprs, NumArgs, rbrac);
+ return Owned(ObjCMessageExpr::Create(Context, ReturnType, LBracLoc,
+ ReceiverTypeInfo, Sel, Method, Args,
+ NumArgs, RBracLoc));
}
-// ActOnInstanceMessage - used for both unary and keyword messages.
+// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
- SourceLocation lbrac,
- SourceLocation receiverLoc,
- SourceLocation rbrac,
- ExprTy **Args, unsigned NumArgs) {
- assert(receiver && "missing receiver expression");
+Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S,
+ TypeTy *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
+ TypeSourceInfo *ReceiverTypeInfo;
+ QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
+ if (ReceiverType.isNull())
+ return ExprError();
- Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
- Expr *RExpr = static_cast<Expr *>(receiver);
- // If necessary, apply function/array conversion to the receiver.
- // C99 6.7.5.3p[7,8].
- DefaultFunctionArrayLvalueConversion(RExpr);
+ if (!ReceiverTypeInfo)
+ ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
- ObjCMethodDecl *Method = 0;
- QualType returnType;
- QualType ReceiverCType =
- Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
+ return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
+ /*SuperLoc=*/SourceLocation(), Sel,
+ LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
- // Handle messages to id.
- if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
- Context.isObjCNSObjectType(RExpr->getType())) {
- // FIXME: If our superclass is NSObject and we message 'super',
- // we'll end up looking in the global method pool??
+/// \brief Build an Objective-C instance message expression.
+///
+/// This routine takes care of both normal instance messages and
+/// instance messages to the superclass instance.
+///
+/// \param Receiver The expression that computes the object that will
+/// receive this message. This may be empty, in which case we are
+/// sending to the superclass instance and \p SuperLoc must be a valid
+/// source location.
+///
+/// \param ReceiverType The (static) type of the object receiving the
+/// message. When a \p Receiver expression is provided, this is the
+/// same type as that expression. For a superclass instance send, this
+/// is a pointer to the type of the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass instance message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param SelectorLoc The location of the first identifier in the selector.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg ArgsIn) {
+ // If we have a receiver expression, perform appropriate promotions
+ // and determine receiver type.
+ Expr *Receiver = ReceiverE.takeAs<Expr>();
+ if (Receiver) {
+ // If necessary, apply function/array conversion to the receiver.
+ // C99 6.7.5.3p[7,8].
+ DefaultFunctionArrayLvalueConversion(Receiver);
+ ReceiverType = Receiver->getType();
+ }
- Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
+ // The location of the receiver.
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+
+ ObjCMethodDecl *Method = 0;
+ // Handle messages to id.
+ if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
+ (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
if (!Method)
- Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
- } else if (ReceiverCType->isObjCClassType() ||
- ReceiverCType->isObjCQualifiedClassType()) {
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ } else if (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
// 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);
}
}
}
// 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) {
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).
// 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));
}
} 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}}
}
id X[] = { [ super superClassMethod] };
return 0;
}
-
-
@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
[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