From: Steve Naroff Date: Thu, 26 Feb 2009 15:55:06 +0000 (+0000) Subject: Fix http://llvm.org/bugs/show_bug.cgi?id=3544. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f1afaf6fe2d94ab265299853f288b676694f7554;p=clang Fix http://llvm.org/bugs/show_bug.cgi?id=3544. The code for looking up local/private method in Sema::ActOnInstanceMessage() was not handling categories properly. Sema::ActOnClassMessage() didn't have this bug. Created a helper with the correct logic and changed both methods to use it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65532 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1120f03f59..533386cab5 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1683,6 +1683,11 @@ public: AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, bool isVariadic = false); + // Helper method for ActOnClassMethod/ActOnInstanceMethod. + // Will search "local" class/category implementations for a method decl. + // Returns 0 if no method is found. + ObjCMethodDecl *LookupPrivateMethod(Selector Sel, ObjCInterfaceDecl *CDecl); + // ActOnClassMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from NumArgs. diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 7696cf0608..e3d2074c0e 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -202,6 +202,27 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return anyIncompatibleArgs; } +// Helper method for ActOnClassMethod/ActOnInstanceMethod. +// Will search "local" class/category implementations for a method decl. +// Returns 0 if no method is found. +ObjCMethodDecl *Sema::LookupPrivateMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl) { + ObjCMethodDecl *Method = 0; + + if (ObjCImplementationDecl *ImpDecl = + ObjCImplementations[ClassDecl->getIdentifier()]) + Method = ImpDecl->getClassMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) { + for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { + if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) + Method = ObjCCategoryImpls[i]->getClassMethod(Sel); + } + } + return Method; +} + // ActOnClassMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). @@ -282,19 +303,9 @@ Sema::ExprResult Sema::ActOnClassMessage( Method = ClassDecl->lookupClassMethod(Sel); // If we have an implementation in scope, check "private" methods. - if (!Method) { - if (ObjCImplementationDecl *ImpDecl = - ObjCImplementations[ClassDecl->getIdentifier()]) - Method = ImpDecl->getClassMethod(Sel); - - // Look through local category implementations associated with the class. - if (!Method) { - for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { - if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) - Method = ObjCCategoryImpls[i]->getClassMethod(Sel); - } - } - } + if (!Method) + Method = LookupPrivateMethod(Sel, ClassDecl); + // Before we give up, check if the selector is an instance method. if (!Method) Method = ClassDecl->lookupInstanceMethod(Sel); @@ -379,12 +390,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // First check the public methods in the class interface. Method = ClassDecl->lookupClassMethod(Sel); - if (!Method) { - // If we have an implementation in scope, check "private" methods. - if (ObjCImplementationDecl *ImpDecl = - ObjCImplementations[ClassDecl->getIdentifier()]) - Method = ImpDecl->getClassMethod(Sel); - } + if (!Method) + Method = LookupPrivateMethod(Sel, ClassDecl); } if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) return true; diff --git a/test/SemaObjC/category-method-lookup-2.m b/test/SemaObjC/category-method-lookup-2.m new file mode 100644 index 0000000000..7bbba8bc4b --- /dev/null +++ b/test/SemaObjC/category-method-lookup-2.m @@ -0,0 +1,22 @@ +// RUN: clang -fsyntax-only -verify %s + +typedef struct objc_class *Class; +@interface NSObject +- (Class)class; +@end +@interface Bar : NSObject +@end +@interface Bar (Cat) +@end + +// NOTE: No class implementation for Bar precedes this category definition. +@implementation Bar (Cat) + +// private method. ++ classMethod { return self; } + +- instanceMethod { + [[self class] classMethod]; +} + +@end \ No newline at end of file