diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 15 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 38 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 12 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 84 |
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() || |