diff options
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 10 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 12 | ||||
-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 | ||||
-rw-r--r-- | test/Parser/objc-quirks.m | 18 | ||||
-rw-r--r-- | test/SemaObjC/call-super-2.m | 2 | ||||
-rw-r--r-- | test/SemaObjC/super.m | 7 |
13 files changed, 142 insertions, 103 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 3e0956fb94..2795851546 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -190,7 +190,9 @@ def err_objc_missing_end : Error<"missing @end">; def warn_objc_protocol_qualifier_missing_id : Warning< "protocol qualifiers without 'id' is archaic">; def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; - +def err_illegal_super_cast : Error< + "cannot cast 'super' (it isn't an expression)">; + def err_objc_illegal_visibility_spec : Error< "illegal visibility specification">; def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7f99cff594..7f7048462f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2011,6 +2011,8 @@ def error_no_super_class : Error< "no super class declared in @interface for %0">; def err_invalid_receiver_to_message : Error< "invalid receiver to message expression">; +def err_invalid_receiver_to_message_super : Error< + "'super' not valid when not in a method">; def warn_bad_receiver_type : Warning< "receiver type %0 is not 'id' or interface pointer, consider " "casting it to 'id'">; @@ -2027,8 +2029,6 @@ def err_catch_param_not_objc_type : Error< "@catch parameter is not a pointer to an interface type">; def err_illegal_qualifiers_on_catch_parm : Error< "illegal qualifiers on @catch parameter">; -def err_illegal_super_cast : Error< - "cannot cast 'super' (it isn't an expression)">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " "use @synthesize, @dynamic or provide a method implementation">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 4e4a1141ab..e030e31d11 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -2336,11 +2336,11 @@ public: return DeclPtrTy(); } - virtual OwningExprResult ActOnClassPropertyRefExpr( - IdentifierInfo &receiverName, - IdentifierInfo &propertyName, - SourceLocation &receiverNameLoc, - SourceLocation &propertyNameLoc) { + virtual OwningExprResult + ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc) { return ExprEmpty(); } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 191ca61a91..7e366c4d27 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -998,18 +998,6 @@ private: //===--------------------------------------------------------------------===// // Objective-C Expressions - - bool isTokObjCMessageIdentifierReceiver() const { - if (!Tok.is(tok::identifier)) - return false; - - IdentifierInfo *II = Tok.getIdentifierInfo(); - if (Actions.getTypeName(*II, Tok.getLocation(), CurScope)) - return true; - - return II == Ident_super; - } - OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation); OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc); OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); 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() || diff --git a/test/Parser/objc-quirks.m b/test/Parser/objc-quirks.m index 62984a458f..b6671d1cf9 100644 --- a/test/Parser/objc-quirks.m +++ b/test/Parser/objc-quirks.m @@ -8,3 +8,21 @@ int @"s" = 5; // expected-error {{prefix attribute must be}} @interface A }; // expected-error {{missing @end}} expected-error {{expected external declaration}} + + + +// PR6811 +// 'super' isn't an expression, it is a magic context-sensitive keyword. +@interface A2 { + id isa; +} +- (void)a; +@end + +@interface B2 : A2 @end +@implementation B2 +- (void)a +{ + [(super) a]; // expected-error {{use of undeclared identifier 'super'}} +} +@end diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m index 9be853b81f..043314d4e1 100644 --- a/test/SemaObjC/call-super-2.m +++ b/test/SemaObjC/call-super-2.m @@ -69,7 +69,7 @@ id objc_getClass(const char *s); - (int) instance_func1 { int i = (size_t)[self instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id'))}} - return i + (size_t)[super instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id')}} + return i + (size_t)[super instance_func0]; // expected-warning {{'Object' may not respond to 'instance_func0')}} } - (int) instance_func2 { diff --git a/test/SemaObjC/super.m b/test/SemaObjC/super.m index a61d72fda5..a644e84e1c 100644 --- a/test/SemaObjC/super.m +++ b/test/SemaObjC/super.m @@ -16,7 +16,7 @@ @implementation B - (void)instanceMethod { - [super iMethod]; // expected-warning{{method '-iMethod' not found (return type defaults to 'id')}} + [super iMethod]; // expected-warning{{'A' may not respond to 'iMethod')}} } + classMethod { @@ -37,12 +37,15 @@ void f0(int super) { expected-warning {{method '-m' not found (return type defaults to 'id')}} } void f1(int puper) { - [super m]; // expected-error{{use of undeclared identifier 'super'}} + [super m]; // expected-error{{'super' not valid when not in a method}} } // radar 7400691 typedef Foo super; +typedef Foo FooTD; + void test() { + [FooTD cMethod]; [super cMethod]; } |