aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ExprObjC.h28
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Parse/Action.h106
-rw-r--r--include/clang/Parse/Parser.h8
-rw-r--r--lib/Parse/ParseExpr.cpp18
-rw-r--r--lib/Parse/ParseInit.cpp55
-rw-r--r--lib/Parse/ParseObjc.cpp104
-rw-r--r--lib/Sema/Sema.h63
-rw-r--r--lib/Sema/SemaCodeComplete.cpp114
-rw-r--r--lib/Sema/SemaExprObjC.cpp477
-rw-r--r--test/SemaObjC/invalid-receiver.m2
-rw-r--r--test/SemaObjC/super.m2
-rw-r--r--test/SemaObjCXX/message.mm4
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