diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.def | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 43 | ||||
-rw-r--r-- | clang/test/SemaObjC/call-super-2.m | 98 | ||||
-rw-r--r-- | clang/test/SemaObjC/conditional-expr.m | 2 | ||||
-rw-r--r-- | clang/test/SemaObjC/property-category-1.m | 2 | ||||
-rw-r--r-- | clang/test/SemaObjC/property-noprotocol-warning.m | 2 |
8 files changed, 136 insertions, 18 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def index 5fb7fe2b299..38977a3ed82 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.def +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def @@ -966,6 +966,8 @@ DIAG(err_catch_param_not_objc_type, ERROR, "@catch parameter is not an Objective-C class type") DIAG(err_illegal_qualifiers_on_catch_parm, ERROR, "illegal qualifiers on @catch parameter") +DIAG(err_illegal_super_cast, ERROR, + "cannot cast 'super' (it isn't an expression)") // C++ casts diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 14b72874f7f..9cb47cce4b2 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -226,6 +226,9 @@ public: /// extremely uncommon (only 1% of selectors are "overloaded"). llvm::DenseMap<Selector, ObjCMethodList> InstanceMethodPool; llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool; + + /// Private Helper predicate to check for 'self'. + bool isSelfExpr(Expr *RExpr); public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer); ~Sema() { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6252bcaef5b..43909b9afe3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2302,6 +2302,8 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { } else if (castType->isVectorType()) { if (CheckVectorCast(TyR, castType, castExpr->getType())) return true; + } else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) { + return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast); } return false; } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 39a89d6d942..8705baffcb6 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -202,6 +202,13 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return anyIncompatibleArgs; } +bool Sema::isSelfExpr(Expr *RExpr) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr)) + if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) + return true; + return false; +} + // Helper method for ActOnClassMethod/ActOnInstanceMethod. // Will search "local" class/category implementations for a method decl. // Returns 0 if no method is found. @@ -385,6 +392,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // Handle messages to Class. if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { ObjCMethodDecl *Method = 0; + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { // First check the public methods in the class interface. @@ -396,12 +404,15 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) return true; } - // Look for any factory method named 'Sel'. - if (!Method) - Method = FactoryMethodPool[Sel].Method; - if (!Method) - Method = LookupInstanceMethodInGlobalPool( - Sel, SourceRange(lbrac,rbrac)); + if (!Method) { + // If not messaging 'self', look for any factory method named 'Sel'. + if (!isSelfExpr(RExpr)) { + Method = FactoryMethodPool[Sel].Method; + if (!Method) + Method = LookupInstanceMethodInGlobalPool( + Sel, SourceRange(lbrac,rbrac)); + } + } if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, lbrac, rbrac, returnType)) return true; @@ -462,15 +473,17 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, } } } - // If we still haven't found a method, look in the global pool. This - // behavior isn't very desirable, however we need it for GCC - // compatibility. FIXME: should we deviate?? - if (!Method && OCIType->qual_empty()) { - Method = LookupInstanceMethodInGlobalPool( - Sel, SourceRange(lbrac,rbrac)); - if (Method && !OCIType->getDecl()->isForwardDecl()) - Diag(lbrac, diag::warn_maynot_respond) - << OCIType->getDecl()->getIdentifier()->getName() << Sel; + if (!isSelfExpr(RExpr)) { + // If we still haven't found a method, look in the global pool. This + // behavior isn't very desirable, however we need it for GCC + // compatibility. FIXME: should we deviate?? + if (!Method && OCIType->qual_empty()) { + Method = LookupInstanceMethodInGlobalPool( + Sel, SourceRange(lbrac,rbrac)); + if (Method && !OCIType->getDecl()->isForwardDecl()) + Diag(lbrac, diag::warn_maynot_respond) + << OCIType->getDecl()->getIdentifier()->getName() << Sel; + } } } if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) diff --git a/clang/test/SemaObjC/call-super-2.m b/clang/test/SemaObjC/call-super-2.m new file mode 100644 index 00000000000..98e4e088576 --- /dev/null +++ b/clang/test/SemaObjC/call-super-2.m @@ -0,0 +1,98 @@ +// RUN: clang -fsyntax-only -verify %s + +#include <stddef.h> + +typedef struct objc_object *id; +id objc_getClass(const char *s); + +@interface Object +@end + +@protocol Func ++ (int) class_func0; +- (int) instance_func0; +@end + +@interface Derived: Object ++ (int) class_func1; ++ (int) class_func2; ++ (int) class_func3; ++ (int) class_func4; ++ (int) class_func5; ++ (int) class_func6; ++ (int) class_func7; +- (int) instance_func1; +- (int) instance_func2; +- (int) instance_func3; +- (int) instance_func4; +- (int) instance_func5; +- (int) instance_func6; +- (int) instance_func7; +@end + +@implementation Derived ++ (int) class_func1 +{ + int i = (size_t)[self class_func0]; // expected-warning {{method '-class_func0' not found (return type defaults to 'id')}} + return i + (size_t)[super class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} +} ++ (int) class_func2 +{ + int i = [(id <Func>)self class_func0]; // expected-warning {{method '-class_func0' not found (return type defaults to 'id')}} // expected-warning {{incompatible pointer to integer conversion initializing 'id', expected 'int'}} + i += [(id <Func>)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} + i += [(Class <Func>)self class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} + return i + [(Class <Func>)super class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func3 +{ + return [(Object <Func> *)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func4 +{ + return [(Derived <Func> *)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func5 +{ + int i = (size_t)[Derived class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} + return i + (size_t)[Object class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} +} ++ (int) class_func6 +{ + return (size_t)[objc_getClass("Object") class_func1]; // GCC warns about this +} ++ (int) class_func7 +{ + return [objc_getClass("Derived") class_func1]; +} +- (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')}} +} +- (int) instance_func2 +{ + return [(id <Func>)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func3 +{ + return [(Object <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func4 +{ + return [(Derived <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func5 +{ + int i = (size_t)[Derived instance_func1]; // GCC currently warns. + return i + (size_t)[Object instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}} +} +- (int) instance_func6 +{ + return (size_t)[objc_getClass("Object") class_func1]; +} +- (int) instance_func7 +{ + return [objc_getClass("Derived") class_func1]; +} +@end + diff --git a/clang/test/SemaObjC/conditional-expr.m b/clang/test/SemaObjC/conditional-expr.m index 76656717e14..4792fa6644d 100644 --- a/clang/test/SemaObjC/conditional-expr.m +++ b/clang/test/SemaObjC/conditional-expr.m @@ -36,7 +36,7 @@ // No @interface declaration for DTFilterOutputStream3 @implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}} - (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream { - id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{DTFilterOutputStream3 may not respond to 'nextOutputStream'}} + id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}} // GCC warns about both of these as well (no errors). self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}} return nextOutputStream ? nextOutputStream : self; diff --git a/clang/test/SemaObjC/property-category-1.m b/clang/test/SemaObjC/property-category-1.m index 926f9642025..243b774870d 100644 --- a/clang/test/SemaObjC/property-category-1.m +++ b/clang/test/SemaObjC/property-category-1.m @@ -1,7 +1,7 @@ // RUN: clang -fsyntax-only -verify %s @interface Object -- (id)new; ++ (id)new; @end @interface ReadOnly : Object diff --git a/clang/test/SemaObjC/property-noprotocol-warning.m b/clang/test/SemaObjC/property-noprotocol-warning.m index 021c7874a99..211185f2b62 100644 --- a/clang/test/SemaObjC/property-noprotocol-warning.m +++ b/clang/test/SemaObjC/property-noprotocol-warning.m @@ -2,7 +2,7 @@ @interface Object -- (id) new; ++ (id) new; @end @protocol GCObject |