diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-21 22:36:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-21 22:36:40 +0000 |
commit | 8d4de67e1d88750ff48392c9b6bd83dce76c785e (patch) | |
tree | 2c9bf7dd252bd3ccc891ac554469c2d8ba1aa966 /clang/lib/Parse/ParseInit.cpp | |
parent | 8e7ebea0b9918a8e8ee2b9a47963877e997a52fb (diff) | |
download | bcm5719-llvm-8d4de67e1d88750ff48392c9b6bd83dce76c785e.tar.gz bcm5719-llvm-8d4de67e1d88750ff48392c9b6bd83dce76c785e.zip |
Implement parsing for message sends in Objective-C++. Message sends in
Objective-C++ have a more complex grammar than in Objective-C
(surprise!), because
(1) The receiver of an instance message can be a qualified name such
as ::I or identity<I>::type.
(2) Expressions in C++ can start with a type.
The receiver grammar isn't actually ambiguous; it just takes a bit of
work to parse past the type before deciding whether we have a type or
expression. We do this in two places within the grammar: once for
message sends and once when we're determining whether a []'d clause in
an initializer list is a message send or a C99 designated initializer.
This implementation of Objective-C++ message sends contains one known
extension beyond GCC's implementation, which is to permit a
typename-specifier as the receiver type for a class message, e.g.,
[typename compute_receiver_type<T>::type method];
Note that the same effect can be achieved in GCC by way of a typedef,
e.g.,
typedef typename computed_receiver_type<T>::type Computed;
[Computed method];
so this is merely a convenience.
Note also that message sends still cannot involve dependent types or
values.
llvm-svn: 102031
Diffstat (limited to 'clang/lib/Parse/ParseInit.cpp')
-rw-r--r-- | clang/lib/Parse/ParseInit.cpp | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp index 1a2a226e683..a382a9ae3c4 100644 --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -34,6 +34,19 @@ static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) { } } +static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, + Designation &Desig) { + // If we have exactly one array designator, this used the GNU + // 'designation: array-designator' extension, otherwise there should be no + // designators at all! + if (Desig.getNumDesignators() == 1 && + (Desig.getDesignator(0).isArrayDesignator() || + Desig.getDesignator(0).isArrayRangeDesignator())) + P.Diag(Loc, diag::ext_gnu_missing_equal_designator); + else if (Desig.getNumDesignators() > 0) + P.Diag(Loc, diag::err_expected_equal_designator); +} + /// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production /// checking to see if the token stream starts with a designator. /// @@ -124,10 +137,46 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { // [4][foo bar] -> obsolete GNU designation with objc message send. // SourceLocation StartLoc = ConsumeBracket(); + OwningExprResult Idx(Actions); + + // If Objective-C is enabled and this is a typename (class message + // send) or send to 'super', parse this as a message send + // expression. We handle C++ and C separately, since C++ requires + // much more complicated parsing. + if (getLang().ObjC1 && getLang().CPlusPlus) { + // Send to 'super'. + if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && + NextToken().isNot(tok::period) && CurScope->isInObjcMethodScope()) { + CheckArrayDesignatorSyntax(*this, StartLoc, Desig); + return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, + ConsumeToken(), 0, + ExprArg(Actions)); + } - // If Objective-C is enabled and this is a typename (class message send) or - // send to 'super', parse this as a message send expression. - if (getLang().ObjC1 && Tok.is(tok::identifier)) { + // Parse the receiver, which is either a type or an expression. + bool IsExpr; + void *TypeOrExpr; + if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { + SkipUntil(tok::r_square); + return ExprError(); + } + + // If the receiver was a type, we have a class message; parse + // the rest of it. + if (!IsExpr) { + CheckArrayDesignatorSyntax(*this, StartLoc, Desig); + return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, + SourceLocation(), + TypeOrExpr, + ExprArg(Actions)); + } + + // If the receiver was an expression, we still don't know + // whether we have a message send or an array designator; just + // adopt the expression for further analysis below. + // FIXME: potentially-potentially evaluated expression above? + Idx = OwningExprResult(Actions, TypeOrExpr); + } else if (getLang().ObjC1 && Tok.is(tok::identifier)) { IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IILoc = Tok.getLocation(); TypeTy *ReceiverType; @@ -141,16 +190,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { ReceiverType)) { 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! - if (Desig.getNumDesignators() == 1 && - (Desig.getDesignator(0).isArrayDesignator() || - Desig.getDesignator(0).isArrayRangeDesignator())) - Diag(StartLoc, diag::ext_gnu_missing_equal_designator); - else if (Desig.getNumDesignators() > 0) - Diag(Tok, diag::err_expected_equal_designator); - + CheckArrayDesignatorSyntax(*this, StartLoc, Desig); if (Kind == Action::ObjCSuperMessage) return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, ConsumeToken(), @@ -175,13 +215,19 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { } } + // Parse the index expression, if we haven't already gotten one + // above (which can only happen in Objective-C++). // Note that we parse this as an assignment expression, not a constant // expression (allowing *=, =, etc) to handle the objc case. Sema needs // to validate that the expression is a constant. - OwningExprResult Idx(ParseAssignmentExpression()); - if (Idx.isInvalid()) { - SkipUntil(tok::r_square); - return move(Idx); + // FIXME: We also need to tell Sema that we're in a + // potentially-potentially evaluated context. + if (!Idx.get()) { + Idx = ParseAssignmentExpression(); + if (Idx.isInvalid()) { + SkipUntil(tok::r_square); + return move(Idx); + } } // Given an expression, we could either have a designator (if the next @@ -190,17 +236,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { // an assignment-expression production. if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) && Tok.isNot(tok::r_square)) { - - // If we have exactly one array designator, this used the GNU - // 'designation: array-designator' extension, otherwise there should be no - // designators at all! - if (Desig.getNumDesignators() == 1 && - (Desig.getDesignator(0).isArrayDesignator() || - Desig.getDesignator(0).isArrayRangeDesignator())) - Diag(StartLoc, diag::ext_gnu_missing_equal_designator); - else if (Desig.getNumDesignators() > 0) - Diag(Tok, diag::err_expected_equal_designator); - + CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig); return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), 0, move(Idx)); |