Skip to content

Commit 0c78ad9

Browse files
committed
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include: - Expanded the interface from two actions (ActOnInstanceMessage, ActOnClassMessage), where ActOnClassMessage also handled sends to "super" by checking whether the identifier was "super", to three actions (ActOnInstanceMessage, ActOnClassMessage, ActOnSuperMessage). Code completion has the same changes. - The parser now resolves the type to which we are sending a class message, so ActOnClassMessage now accepts a TypeTy* (rather than an IdentifierInfo *). This opens the door to more interesting types (for Objective-C++ support). - Split ActOnInstanceMessage and ActOnClassMessage into parser action functions (with their original names) and semantic functions (BuildInstanceMessage and BuildClassMessage, respectively). At present, this split is onyl used by ActOnSuperMessage, which decides which kind of super message it has and forwards to the appropriate Build*Message. In the future, Build*Message will be used by template instantiation. - Use getObjCMessageKind() within the disambiguation of Objective-C message sends vs. array designators. Two notes about substandard bits in this patch: - There is some redundancy in the code in ParseObjCMessageExpr and ParseInitializerWithPotentialDesignator; this will be addressed shortly by centralizing the mapping from identifiers to type names for the message receiver. - There is some #if 0'd code that won't likely ever be used---it handles the use of 'super' in methods whose class does not have a superclass---but could be used to model GCC's behavior more closely. This code will die in my next check-in, but I want it in Subversion. llvm-svn: 102021
1 parent 43c64af commit 0c78ad9

File tree

13 files changed

+674
-309
lines changed

13 files changed

+674
-309
lines changed

clang/include/clang/AST/ExprObjC.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,29 @@ class ObjCImplicitSetterGetterRefExpr : public Expr {
343343
virtual child_iterator child_end();
344344
};
345345

346+
/// \brief An expression that sends a message to the given Objective-C
347+
/// object or class.
348+
///
349+
/// The following contains two message send expressions:
350+
///
351+
/// \code
352+
/// [[NSString alloc] initWithString:@"Hello"]
353+
/// \endcode
354+
///
355+
/// The innermost message send invokes the "alloc" class method on the
356+
/// NSString class, while the outermost message send invokes the
357+
/// "initWithString" instance method on the object returned from
358+
/// NSString's "alloc". In all, an Objective-C message send can take
359+
/// on four different (although related) forms:
360+
///
361+
/// 1. Send to an object instance.
362+
/// 2. Send to a class.
363+
/// 3. Send to the superclass instance of the current class.
364+
/// 4. Send to the superclass of the current class.
365+
///
366+
/// All four kinds of message sends are modeled by the ObjCMessageExpr
367+
/// class, and can be distinguished via \c getReceiverKind(). Example:
368+
///
346369
class ObjCMessageExpr : public Expr {
347370
/// \brief The number of arguments in the message send, not
348371
/// including the receiver.
@@ -402,7 +425,7 @@ class ObjCMessageExpr : public Expr {
402425
Expr **Args, unsigned NumArgs,
403426
SourceLocation RBracLoc);
404427

405-
/// \brief Retrieve the pointer value of the ,message receiver.
428+
/// \brief Retrieve the pointer value of the message receiver.
406429
void *getReceiverPointer() const {
407430
return *const_cast<void **>(
408431
reinterpret_cast<const void * const*>(this + 1));
@@ -712,6 +735,9 @@ class ObjCMessageExpr : public Expr {
712735

713736
/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
714737
/// which refers to the object on which the current method is executing.
738+
///
739+
/// FIXME: This class is intended for removal, once its remaining
740+
/// clients have been altered to represent "super" internally.
715741
class ObjCSuperExpr : public Expr {
716742
SourceLocation Loc;
717743
public:

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,8 @@ def err_invalid_receiver_to_message : Error<
20462046
"invalid receiver to message expression">;
20472047
def err_invalid_receiver_to_message_super : Error<
20482048
"'super' is only valid in a method body">;
2049+
def err_invalid_receiver_class_message : Error<
2050+
"receiver type %0 is not an Objective-C class">;
20492051
def warn_bad_receiver_type : Warning<
20502052
"receiver type %0 is not 'id' or interface pointer, consider "
20512053
"casting it to 'id'">;

clang/include/clang/Parse/Action.h

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,29 +2389,63 @@ class Action : public ActionBase {
23892389
SourceLocation NameLoc,
23902390
bool IsSuper,
23912391
bool HasTrailingDot);
2392-
2393-
// ActOnClassMessage - used for both unary and keyword messages.
2394-
// ArgExprs is optional - if it is present, the number of expressions
2395-
// is obtained from NumArgs.
2396-
virtual ExprResult ActOnClassMessage(
2397-
Scope *S,
2398-
IdentifierInfo *receivingClassName,
2399-
Selector Sel,
2400-
SourceLocation lbrac, SourceLocation receiverLoc,
2401-
SourceLocation selectorLoc,
2402-
SourceLocation rbrac,
2403-
ExprTy **ArgExprs, unsigned NumArgs) {
2404-
return ExprResult();
2405-
}
2406-
// ActOnInstanceMessage - used for both unary and keyword messages.
2407-
// ArgExprs is optional - if it is present, the number of expressions
2408-
// is obtained from NumArgs.
2409-
virtual ExprResult ActOnInstanceMessage(
2410-
ExprTy *receiver, Selector Sel,
2411-
SourceLocation lbrac, SourceLocation selectorLoc, SourceLocation rbrac,
2412-
ExprTy **ArgExprs, unsigned NumArgs) {
2413-
return ExprResult();
2392+
2393+
/// \brief Parsed a message send to 'super'.
2394+
///
2395+
/// \param S The scope in which the message send occurs.
2396+
/// \param SuperLoc The location of the 'super' keyword.
2397+
/// \param Sel The selector to which the message is being sent.
2398+
/// \param LBracLoc The location of the opening square bracket ']'.
2399+
/// \param SelectorLoc The location of the first identifier in the selector.
2400+
/// \param RBrac The location of the closing square bracket ']'.
2401+
/// \param Args The message arguments.
2402+
virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
2403+
Selector Sel,
2404+
SourceLocation LBracLoc,
2405+
SourceLocation SelectorLoc,
2406+
SourceLocation RBracLoc,
2407+
MultiExprArg Args) {
2408+
return OwningExprResult(*this);
2409+
}
2410+
2411+
/// \brief Parsed a message send to a class.
2412+
///
2413+
/// \param S The scope in which the message send occurs.
2414+
/// \param Receiver The type of the class receiving the message.
2415+
/// \param Sel The selector to which the message is being sent.
2416+
/// \param LBracLoc The location of the opening square bracket ']'.
2417+
/// \param SelectorLoc The location of the first identifier in the selector.
2418+
/// \param RBrac The location of the closing square bracket ']'.
2419+
/// \param Args The message arguments.
2420+
virtual OwningExprResult ActOnClassMessage(Scope *S,
2421+
TypeTy *Receiver,
2422+
Selector Sel,
2423+
SourceLocation LBracLoc,
2424+
SourceLocation SelectorLoc,
2425+
SourceLocation RBracLoc,
2426+
MultiExprArg Args) {
2427+
return OwningExprResult(*this);
2428+
}
2429+
2430+
/// \brief Parsed a message send to an object instance.
2431+
///
2432+
/// \param S The scope in which the message send occurs.
2433+
/// \param Receiver The expression that computes the receiver object.
2434+
/// \param Sel The selector to which the message is being sent.
2435+
/// \param LBracLoc The location of the opening square bracket ']'.
2436+
/// \param SelectorLoc The location of the first identifier in the selector.
2437+
/// \param RBrac The location of the closing square bracket ']'.
2438+
/// \param Args The message arguments.
2439+
virtual OwningExprResult ActOnInstanceMessage(Scope *S,
2440+
ExprArg Receiver,
2441+
Selector Sel,
2442+
SourceLocation LBracLoc,
2443+
SourceLocation SelectorLoc,
2444+
SourceLocation RBracLoc,
2445+
MultiExprArg Args) {
2446+
return OwningExprResult(*this);
24142447
}
2448+
24152449
virtual DeclPtrTy ActOnForwardClassDeclaration(
24162450
SourceLocation AtClassLoc,
24172451
IdentifierInfo **IdentList,
@@ -2738,21 +2772,33 @@ class Action : public ActionBase {
27382772
unsigned NumMethods) {
27392773
}
27402774

2775+
/// \brief Code completion for an ObjC message expression that sends
2776+
/// a message to the superclass.
2777+
///
2778+
/// This code completion action is invoked when the code-completion token is
2779+
/// found after the class name and after each argument.
2780+
///
2781+
/// \param S The scope in which the message expression occurs.
2782+
/// \param SuperLoc The location of the 'super' keyword.
2783+
/// \param SelIdents The identifiers that describe the selector (thus far).
2784+
/// \param NumSelIdents The number of identifiers in \p SelIdents.
2785+
virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
2786+
IdentifierInfo **SelIdents,
2787+
unsigned NumSelIdents) { }
2788+
27412789
/// \brief Code completion for an ObjC message expression that refers to
27422790
/// a class method.
27432791
///
27442792
/// This code completion action is invoked when the code-completion token is
27452793
/// found after the class name and after each argument.
27462794
///
2747-
/// \param S the scope in which the message expression occurs.
2748-
/// \param FName the factory name.
2749-
/// \param FNameLoc the source location of the factory name.
2750-
/// \param SelIdents the identifiers that describe the selector (thus far).
2751-
/// \param NumSelIdents the number of identifiers in \p SelIdents.
2752-
virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
2753-
SourceLocation FNameLoc,
2795+
/// \param S The scope in which the message expression occurs.
2796+
/// \param Receiver The type of the class that is receiving a message.
2797+
/// \param SelIdents The identifiers that describe the selector (thus far).
2798+
/// \param NumSelIdents The number of identifiers in \p SelIdents.
2799+
virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
27542800
IdentifierInfo **SelIdents,
2755-
unsigned NumSelIdents){ }
2801+
unsigned NumSelIdents) { }
27562802

27572803
/// \brief Code completion for an ObjC message expression that refers to
27582804
/// an instance method.

clang/include/clang/Parse/Parser.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,12 +1005,12 @@ class Parser {
10051005
OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
10061006
OwningExprResult ParseObjCMessageExpression();
10071007
OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
1008-
SourceLocation NameLoc,
1009-
IdentifierInfo *ReceiverName,
1008+
SourceLocation SuperLoc,
1009+
TypeTy *ReceiverType,
10101010
ExprArg ReceiverExpr);
10111011
OwningExprResult ParseAssignmentExprWithObjCMessageExprStart(
1012-
SourceLocation LBracloc, SourceLocation NameLoc,
1013-
IdentifierInfo *ReceiverName, ExprArg ReceiverExpr);
1012+
SourceLocation LBracloc, SourceLocation SuperLoc,
1013+
TypeTy *ReceiverType, ExprArg ReceiverExpr);
10141014

10151015
//===--------------------------------------------------------------------===//
10161016
// C99 6.8: Statements and Blocks.

clang/lib/Parse/ParseExpr.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,11 @@ Parser::OwningExprResult Parser::ParseAssignmentExpression() {
268268
/// expressions and other binary operators for these expressions as well.
269269
Parser::OwningExprResult
270270
Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
271-
SourceLocation NameLoc,
272-
IdentifierInfo *ReceiverName,
271+
SourceLocation SuperLoc,
272+
TypeTy *ReceiverType,
273273
ExprArg ReceiverExpr) {
274-
OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc,
275-
ReceiverName,
274+
OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
275+
ReceiverType,
276276
move(ReceiverExpr)));
277277
if (R.isInvalid()) return move(R);
278278
R = ParsePostfixExpressionSuffix(move(R));
@@ -481,7 +481,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
481481
/// [OBJC] '@encode' '(' type-name ')'
482482
/// [OBJC] objc-string-literal
483483
/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
484-
/// [C++] typename-specifier '(' expression-list[opt] ')' [TODO]
484+
/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
485485
/// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
486486
/// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
487487
/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
@@ -501,14 +501,14 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
501501
///
502502
/// id-expression: [C++ 5.1]
503503
/// unqualified-id
504-
/// qualified-id [TODO]
504+
/// qualified-id
505505
///
506506
/// unqualified-id: [C++ 5.1]
507507
/// identifier
508508
/// operator-function-id
509-
/// conversion-function-id [TODO]
510-
/// '~' class-name [TODO]
511-
/// template-id [TODO]
509+
/// conversion-function-id
510+
/// '~' class-name
511+
/// template-id
512512
///
513513
/// new-expression: [C++ 5.3.4]
514514
/// '::'[opt] 'new' new-placement[opt] new-type-id

clang/lib/Parse/ParseInit.cpp

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,16 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
129129
// send to 'super', parse this as a message send expression.
130130
if (getLang().ObjC1 && Tok.is(tok::identifier)) {
131131
IdentifierInfo *II = Tok.getIdentifierInfo();
132-
132+
SourceLocation IILoc = Tok.getLocation();
133133
// Three cases. This is a message send to a type: [type foo]
134134
// This is a message send to super: [super foo]
135135
// This is a message sent to an expr: [super.bar foo]
136-
if (Actions.getTypeName(*II, Tok.getLocation(), CurScope) ||
137-
(II == Ident_super && GetLookAheadToken(1).isNot(tok::period) &&
138-
CurScope->isInObjcMethodScope())) {
136+
switch (Action::ObjCMessageKind Kind
137+
= Actions.getObjCMessageKind(CurScope, II, IILoc,
138+
II == Ident_super,
139+
NextToken().is(tok::period))) {
140+
case Action::ObjCSuperMessage:
141+
case Action::ObjCClassMessage: {
139142
// If we have exactly one array designator, this used the GNU
140143
// 'designation: array-designator' extension, otherwise there should be no
141144
// designators at all!
@@ -146,9 +149,47 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
146149
else if (Desig.getNumDesignators() > 0)
147150
Diag(Tok, diag::err_expected_equal_designator);
148151

149-
SourceLocation NameLoc = ConsumeToken();
150-
return ParseAssignmentExprWithObjCMessageExprStart(
151-
StartLoc, NameLoc, II, ExprArg(Actions));
152+
if (Kind == Action::ObjCSuperMessage)
153+
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
154+
ConsumeToken(),
155+
0,
156+
ExprArg(Actions));
157+
158+
// FIXME: This code is redundant with ParseObjCMessageExpr.
159+
// Create the type that corresponds to the identifier (which
160+
// names an Objective-C class).
161+
TypeTy *Type = 0;
162+
if (TypeTy *TyName = Actions.getTypeName(*II, IILoc, CurScope)) {
163+
DeclSpec DS;
164+
const char *PrevSpec = 0;
165+
unsigned DiagID = 0;
166+
if (!DS.SetTypeSpecType(DeclSpec::TST_typename, IILoc, PrevSpec,
167+
DiagID, TyName)) {
168+
DS.SetRangeEnd(IILoc);
169+
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
170+
TypeResult Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo);
171+
if (!Ty.isInvalid())
172+
Type = Ty.get();
173+
}
174+
}
175+
176+
ConsumeToken(); // The identifier.
177+
if (!Type) {
178+
SkipUntil(tok::r_square);
179+
return ExprError();
180+
}
181+
182+
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
183+
SourceLocation(),
184+
Type,
185+
ExprArg(Actions));
186+
}
187+
188+
case Action::ObjCInstanceMessage:
189+
// Fall through; we'll just parse the expression and
190+
// (possibly) treat this like an Objective-C message send
191+
// later.
192+
break;
152193
}
153194
}
154195

0 commit comments

Comments
 (0)