diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-21 19:57:20 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-21 19:57:20 +0000 |
commit | 2725ca8eb3354975ca77ed4b88ede7b60b216b9a (patch) | |
tree | e26d416a79f5feb5703e8bfc50ace56e91546f4d /lib/Parse | |
parent | 711f34adb886cce8ba86c7b1b6513a1eaaf63bb5 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102021 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 18 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 104 |
3 files changed, 138 insertions, 39 deletions
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) { |