Introduce a parsing action to distinguish between class, instance, and

super message sends in Objective-C. No actual functionality change
here, but it provides a hook so that Sema can typo-correct the
receiver in some cases.

llvm-svn: 101207
This commit is contained in:
Douglas Gregor 2010-04-14 02:22:16 +00:00
parent 9162fb07be
commit a148a1d40e
3 changed files with 71 additions and 10 deletions

View File

@ -2344,6 +2344,52 @@ public:
return ExprEmpty();
}
/// \brief Describes the kind of message expression indicated by a message
/// send that starts with an identifier.
enum ObjCMessageKind {
/// \brief The message is sent to 'super'.
ObjCSuperMessage,
/// \brief The message is an instance message.
ObjCInstanceMessage,
/// \brief The message is a class message, and the identifier is a type
/// name.
ObjCClassMessage
};
/// \brief Determine the kind of Objective-C message send that we will be
/// performing based on the identifier given.
///
/// This action determines how a message send that starts with [
/// identifier (followed by another identifier) will be parsed,
/// e.g., as a class message, instance message, super message. The
/// result depends on the meaning of the given identifier. If the
/// identifier is unknown, the action should indicate that the
/// message is an instance message.
///
/// By default, this routine applies syntactic disambiguation and uses
/// \c getTypeName() to determine whether the identifier refers to a type.
/// However, \c Action subclasses may override this routine to improve
/// error recovery.
///
/// \param S The scope in which the message send occurs.
///
/// \param Name The identifier following the '['. This identifier
/// may be modified by the action, if, for example, typo-correction
/// finds a different class name.
///
/// \param NameLoc The location of the identifier.
///
/// \param IsSuper Whether the name is the pseudo-keyword "super".
///
/// \param HasTrailingDot Whether the name is followed by a period.
///
/// \returns The kind of message send.
virtual ObjCMessageKind getObjCMessageKind(Scope *S,
IdentifierInfo *&Name,
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.

View File

@ -26,6 +26,20 @@ ActionBase::~ActionBase() {}
/// Out-of-line virtual destructor to provide home for Action class.
Action::~Action() {}
Action::ObjCMessageKind Action::getObjCMessageKind(Scope *S,
IdentifierInfo *&Name,
SourceLocation NameLoc,
bool IsSuper,
bool HasTrailingDot) {
if (IsSuper && !HasTrailingDot && S->isInObjcMethodScope())
return ObjCSuperMessage;
if (getTypeName(*Name, NameLoc, S))
return ObjCClassMessage;
return ObjCInstanceMessage;
}
// Defined out-of-line here because of dependecy on AttributeList
Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
SourceLocation UsingLoc,

View File

@ -1719,17 +1719,18 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
if (Tok.is(tok::identifier)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
// If this is '[' 'super', then this is a magic superclass message.
// We parse '[' 'super' '.' 'foo' as an expression?
if ((II == Ident_super && GetLookAheadToken(1).isNot(tok::period) &&
CurScope->isInObjcMethodScope()) ||
// Check to see if this is a typename. If so, it is a class message.
Actions.getTypeName(*II, Tok.getLocation(), CurScope)) {
SourceLocation NameLoc = ConsumeToken();
return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, II,
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = Tok.getLocation();
switch (Actions.getObjCMessageKind(CurScope, Name, NameLoc,
Name == Ident_super,
NextToken().is(tok::period))) {
case Action::ObjCSuperMessage:
case Action::ObjCClassMessage:
return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), Name,
ExprArg(Actions));
case Action::ObjCInstanceMessage:
break;
}
}