aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseExpr.cpp15
-rw-r--r--lib/Parse/ParseInit.cpp38
-rw-r--r--lib/Parse/ParseObjc.cpp19
-rw-r--r--lib/Sema/Sema.h12
-rw-r--r--lib/Sema/SemaExpr.cpp20
-rw-r--r--lib/Sema/SemaExprObjC.cpp84
6 files changed, 108 insertions, 80 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 965f764dcf..ad422642e4 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -637,11 +637,9 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
IdentifierInfo &II = *Tok.getIdentifierInfo();
SourceLocation ILoc = ConsumeToken();
- // Support 'Class.property' notation. We don't use
- // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
- // inappropriate here).
+ // Support 'Class.property' and 'super.property' notation.
if (getLang().ObjC1 && Tok.is(tok::period) &&
- Actions.getTypeName(II, ILoc, CurScope)) {
+ (Actions.getTypeName(II, ILoc, CurScope) || II.isStr("super"))) {
SourceLocation DotLoc = ConsumeToken();
if (Tok.isNot(tok::identifier)) {
@@ -1441,6 +1439,15 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// returns the parsed type to the callee.
return OwningExprResult(Actions);
}
+
+
+ // Reject the cast of super idiom in ObjC.
+ if (Tok.is(tok::identifier) && getLang().ObjC1 &&
+ Tok.getIdentifierInfo()->isStr("super")) {
+ Diag(Tok.getLocation(), diag::err_illegal_super_cast)
+ << SourceRange(OpenLoc, RParenLoc);
+ return ExprError();
+ }
// Parse the cast-expression that follows it next.
// TODO: For cast expression with CastTy.
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 9154d8d599..57751c9c3f 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -124,23 +124,27 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
//
SourceLocation StartLoc = ConsumeBracket();
- // 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 Objective-C is enabled and this is a typename (class message send) or
+ // 'super', parse this as a message send expression.
+ if (getLang().ObjC1 && Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (II == Ident_super || Actions.getTypeName(*II, Tok.getLocation(),
+ CurScope)) {
+ // 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);
+
+ SourceLocation NameLoc = ConsumeToken();
+ return ParseAssignmentExprWithObjCMessageExprStart(
+ StartLoc, NameLoc, II, ExprArg(Actions));
+ }
}
// Note that we parse this as an assignment expression, not a constant
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index cd42aee255..6e31f0f63c 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1709,6 +1709,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
/// '[' objc-receiver objc-message-args ']'
///
/// objc-receiver:
+/// 'super'
/// expression
/// class-name
/// type-name
@@ -1716,16 +1717,22 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
assert(Tok.is(tok::l_square) && "'[' expected");
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
- // Parse receiver
- if (isTokObjCMessageIdentifierReceiver()) {
- IdentifierInfo *ReceiverName = Tok.getIdentifierInfo();
- if (ReceiverName != Ident_super || GetLookAheadToken(1).isNot(tok::period)) {
+ 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?
+ // FIXME: Not in ParseInit.cpp?
+ if ((II == Ident_super && GetLookAheadToken(1).isNot(tok::period)) ||
+ // 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, ReceiverName,
+ return ParseObjCMessageExpressionBody(LBracLoc, NameLoc, II,
ExprArg(Actions));
}
}
-
+
+ // Otherwise, an arbitrary expression can be the receiver of a send.
OwningExprResult Res(ParseExpression());
if (Res.isInvalid()) {
SkipUntil(tok::r_square);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index d6476be685..822e95971c 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3845,17 +3845,17 @@ public:
ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
ObjCInterfaceDecl *ClassDecl);
- Action::OwningExprResult
+ OwningExprResult
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr,
DeclarationName MemberName,
SourceLocation MemberLoc);
- virtual OwningExprResult ActOnClassPropertyRefExpr(
- IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation &receiverNameLoc,
- SourceLocation &propertyNameLoc);
+ virtual OwningExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c173705be5..54f74d5d6e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1233,10 +1233,11 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
/// Returns a null sentinel to indicate trivial success.
Sema::OwningExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
- IdentifierInfo *II,
- bool AllowBuiltinCreation) {
+ IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
+ // FIXME: Stop re-evaluating "getCurMethodDecl".
+
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
// found a decl, but that decl is outside the current instance method (i.e.
@@ -1304,17 +1305,6 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
- // Needed to implement property "super.method" notation.
- if (Lookup.empty() && II->isStr("super")) {
- QualType T;
-
- if (getCurMethodDecl()->isInstanceMethod())
- T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
- else
- T = Context.getObjCClassType();
- return Owned(new (Context) ObjCSuperExpr(Loc, T));
- }
if (Lookup.empty() && II && AllowBuiltinCreation) {
// FIXME. Consolidate this with similar code in LookupName.
if (unsigned BuiltinID = II->getBuiltinID()) {
@@ -3138,6 +3128,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
<< MemberName << BaseType);
}
+
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
if (!IsArrow)
@@ -3850,9 +3841,6 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
if (castExpr->getType()->isVectorType())
return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
- if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
- return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
-
if (isa<ObjCSelectorExpr>(castExpr))
return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 327e294f36..9ada985cdc 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -394,20 +394,42 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
-Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
- IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation &receiverNameLoc,
- SourceLocation &propertyNameLoc) {
+Action::OwningExprResult Sema::
+ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc) {
IdentifierInfo *receiverNamePtr = &receiverName;
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
- if (!IFace) {
- Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
- return ExprError();
+ if (IFace == 0) {
+ // If the "receiver" is 'super' in a method, handle it as an expression-like
+ // property reference.
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+ if (receiverNamePtr->isStr("super")) {
+ if (CurMethod->isInstanceMethod()) {
+ QualType T =
+ Context.getObjCInterfaceType(CurMethod->getClassInterface());
+ T = Context.getObjCObjectPointerType(T);
+ Expr *SuperExpr = new (Context) ObjCSuperExpr(receiverNameLoc, T);
+
+ return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+ SuperExpr, &propertyName,
+ propertyNameLoc);
+ }
+
+ // Otherwise, if this is a class method, try dispatching to our
+ // superclass.
+ IFace = CurMethod->getClassInterface()->getSuperClass();
+ }
+
+ if (IFace == 0) {
+ Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+ return ExprError();
+ }
}
- // Search for a declared property first.
+ // Search for a declared property first.
Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
@@ -468,12 +490,11 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
-Sema::ExprResult Sema::ActOnClassMessage(
- Scope *S,
- IdentifierInfo *receiverName, Selector Sel,
- SourceLocation lbrac, SourceLocation receiverLoc,
- SourceLocation selectorLoc, SourceLocation rbrac,
- ExprTy **Args, unsigned NumArgs) {
+Sema::ExprResult Sema::
+ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel,
+ SourceLocation lbrac, SourceLocation receiverLoc,
+ SourceLocation selectorLoc, SourceLocation rbrac,
+ ExprTy **Args, unsigned NumArgs) {
assert(receiverName && "missing receiver class name");
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
@@ -481,16 +502,16 @@ Sema::ExprResult Sema::ActOnClassMessage(
bool isSuper = false;
if (receiverName->isStr("super")) {
- if (getCurMethodDecl()) {
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
isSuper = true;
- ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
+ ObjCInterfaceDecl *OID = CurMethod->getClassInterface();
if (!OID)
return Diag(lbrac, diag::error_no_super_class_message)
- << getCurMethodDecl()->getDeclName();
+ << CurMethod->getDeclName();
ClassDecl = OID->getSuperClass();
if (!ClassDecl)
return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
- if (getCurMethodDecl()->isInstanceMethod()) {
+ if (CurMethod->isInstanceMethod()) {
QualType superTy = Context.getObjCInterfaceType(ClassDecl);
superTy = Context.getObjCObjectPointerType(superTy);
ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
@@ -504,6 +525,11 @@ Sema::ExprResult Sema::ActOnClassMessage(
} else {
// 'super' has been used outside a method context. If a variable named
// 'super' has been declared, redirect. If not, produce a diagnostic.
+
+ // FIXME:
+ // FIXME: This should be handled in the parser!
+ // FIXME:
+
NamedDecl *SuperDecl
= LookupSingleName(S, receiverName, LookupOrdinaryName);
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
@@ -514,17 +540,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
selectorLoc, rbrac, Args, NumArgs);
}
- else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
- const ObjCInterfaceType *OCIT;
- OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
- if (!OCIT) {
- Diag(receiverLoc, diag::err_invalid_receiver_to_message);
- return true;
- }
- ClassDecl = OCIT->getDecl();
- }
- else
- return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
+ ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
}
} else
ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
@@ -548,7 +564,11 @@ Sema::ExprResult Sema::ActOnClassMessage(
ClassDecl = OCIT->getDecl();
if (!ClassDecl) {
- Diag(receiverLoc, diag::err_invalid_receiver_to_message);
+ // Give a better error message for invalid use of super.
+ if (receiverName->isStr("super"))
+ Diag(receiverLoc, diag::err_invalid_receiver_to_message_super);
+ else
+ Diag(receiverLoc, diag::err_invalid_receiver_to_message);
return true;
}
}
@@ -616,6 +636,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
QualType ReceiverCType =
Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
+#if 0
// Handle messages to 'super'.
if (isa<ObjCSuperExpr>(RExpr)) {
ObjCMethodDecl *Method = 0;
@@ -643,6 +664,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
Method, lbrac, rbrac,
ArgExprs, NumArgs);
}
+#endif
// Handle messages to id.
if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||