зеркало из https://github.com/microsoft/clang-1.git
fix PR6811 by not parsing 'super' as a magic expression in
LookupInObjCMethod. Doing so allows all sorts of invalid code to slip through to codegen. This patch does not change the AST representation of super, though that would now be a natural thing to do since it can only be in the receiver position and in the base of a ObjCPropertyRefExpr. There are still several ugly areas handling super in the parser, but this is definitely a step in the right direction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100959 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b9d4fc1f54
Коммит
eb483eb3ee
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
// 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();
|
||||
|
||||
IdentifierInfo *Name = Tok.getIdentifierInfo();
|
||||
SourceLocation NameLoc = ConsumeToken();
|
||||
return ParseAssignmentExprWithObjCMessageExprStart(
|
||||
StartLoc, NameLoc, Name, ExprArg(Actions));
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
// Search for a declared property first.
|
||||
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.
|
||||
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() ||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче