aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseInit.cpp')
-rw-r--r--lib/Parse/ParseInit.cpp132
1 files changed, 100 insertions, 32 deletions
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 9154d8d59987..a382a9ae3c40 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Designator.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Scope.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -33,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.
///
@@ -123,33 +137,97 @@ 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));
+ }
+
+ // 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 Objective-C is enabled and this is a typename or other identifier
- // receiver, parse this as a message send expression.
- if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
- // 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);
-
- IdentifierInfo *Name = Tok.getIdentifierInfo();
- SourceLocation NameLoc = ConsumeToken();
- return ParseAssignmentExprWithObjCMessageExprStart(
- StartLoc, NameLoc, Name, 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;
+ // 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]
+ switch (Action::ObjCMessageKind Kind
+ = Actions.getObjCMessageKind(CurScope, II, IILoc,
+ II == Ident_super,
+ NextToken().is(tok::period),
+ ReceiverType)) {
+ case Action::ObjCSuperMessage:
+ case Action::ObjCClassMessage:
+ CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
+ if (Kind == Action::ObjCSuperMessage)
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ ConsumeToken(),
+ 0,
+ ExprArg(Actions));
+ ConsumeToken(); // the identifier
+ if (!ReceiverType) {
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ SourceLocation(),
+ ReceiverType,
+ 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;
+ }
}
+ // 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
@@ -158,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));