From: Anna Zaks Date: Fri, 27 Jul 2012 19:07:44 +0000 (+0000) Subject: Consolidate ObjC lookupPrivateMethod methods from Sema and DeclObjC. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e61354b274ec5aa6acf3d15271896ce7596bb123;p=clang Consolidate ObjC lookupPrivateMethod methods from Sema and DeclObjC. Also, fix a subtle bug, which occurred due to lookupPrivateMethod defined in DeclObjC.h not looking up the method inside parent's categories. Note, the code assumes that Class's parent object has the same methods as what's in the Root class of a the hierarchy, which is a heuristic that might not hold for hierarchies which do not descend from NSObject. Would be great to fix this in the future. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160885 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 0b3e56e6e3..4229fd3c0d 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -939,9 +939,13 @@ public: } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); - // Lookup a method in the classes implementation hierarchy. + /// \brief Lookup a method in the classes implementation hierarchy. ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true); + ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) { + return lookupPrivateMethod(Sel, false); + } + SourceLocation getEndOfDefinitionLoc() const { if (!hasDefinition()) return getLocation(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9675e08e4a..bce285d897 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6107,14 +6107,6 @@ public: AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, bool isVariadic, bool MethodDefinition); - // Helper method for ActOnClassMethod/ActOnInstanceMethod. - // Will search "local" class/category implementations for a method decl. - // Will also search in class's root looking for instance method. - // Returns 0 if no method is found. - ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel, - ObjCInterfaceDecl *CDecl); - ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, - ObjCInterfaceDecl *ClassDecl); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, bool IsInstance); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 39f09063e9..cbd15240b1 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -363,6 +363,9 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return NULL; } +// Will search "local" class/category implementations for a method decl. +// If failed, then we search in class's root for an instance method. +// Returns 0 if no method is found. ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( const Selector &Sel, bool Instance) { @@ -377,7 +380,23 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( if (ObjCImplementationDecl *ImpDecl = getImplementation()) Method = Instance ? ImpDecl->getInstanceMethod(Sel) : ImpDecl->getClassMethod(Sel); - + + // Look through local category implementations associated with the class. + if (!Method) + Method = Instance ? getCategoryInstanceMethod(Sel) + : getCategoryClassMethod(Sel); + + // Before we give up, check if the selector is an instance method. + // But only in the root. This matches gcc's behavior and what the + // runtime expects. + if (!Instance && !Method && !getSuperClass()) { + Method = lookupInstanceMethod(Sel); + // Look through local category implementations associated + // with the root class. + if (!Method) + Method = lookupPrivateMethod(Sel, true); + } + if (!Method && getSuperClass()) return getSuperClass()->lookupPrivateMethod(Sel, Instance); return Method; diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index d5e83ce8ae..79973b352f 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -1366,9 +1366,6 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // methods. Setter = IFace->lookupPrivateMethod(SetterSel, false); } - // Look through local category implementations associated with the class. - if (!Setter) - Setter = IFace->getCategoryClassMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 1cdacdec89..31dfae9055 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1247,57 +1247,6 @@ bool Sema::isSelfExpr(Expr *receiver) { return false; } -// Helper method for ActOnClassMethod/ActOnInstanceMethod. -// Will search "local" class/category implementations for a method decl. -// If failed, then we search in class's root for an instance method. -// Returns 0 if no method is found. -ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, - ObjCInterfaceDecl *ClassDecl) { - ObjCMethodDecl *Method = 0; - // lookup in class and all superclasses - while (ClassDecl && !Method) { - if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) - Method = ImpDecl->getClassMethod(Sel); - - // Look through local category implementations associated with the class. - if (!Method) - Method = ClassDecl->getCategoryClassMethod(Sel); - - // Before we give up, check if the selector is an instance method. - // But only in the root. This matches gcc's behaviour and what the - // runtime expects. - if (!Method && !ClassDecl->getSuperClass()) { - Method = ClassDecl->lookupInstanceMethod(Sel); - // Look through local category implementations associated - // with the root class. - if (!Method) - Method = LookupPrivateInstanceMethod(Sel, ClassDecl); - } - - ClassDecl = ClassDecl->getSuperClass(); - } - return Method; -} - -ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, - ObjCInterfaceDecl *ClassDecl) { - if (!ClassDecl->hasDefinition()) - return 0; - - ObjCMethodDecl *Method = 0; - while (ClassDecl && !Method) { - // If we have implementations in scope, check "private" methods. - if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) - Method = ImpDecl->getInstanceMethod(Sel); - - // Look through local category implementations associated with the class. - if (!Method) - Method = ClassDecl->getCategoryInstanceMethod(Sel); - ClassDecl = ClassDecl->getSuperClass(); - } - return Method; -} - /// LookupMethodInType - Look up a method in an ObjCObjectType. ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, bool isInstance) { @@ -1309,13 +1258,8 @@ ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, // Okay, look for "private" methods declared in any // @implementations we've seen. - if (isInstance) { - if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface)) - return method; - } else { - if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface)) - return method; - } + if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance)) + return method; } // Check qualifiers. @@ -1489,9 +1433,6 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (!Getter) Getter = IFace->lookupPrivateMethod(Sel); - // Look through local category implementations associated with the class. - if (!Getter) - Getter = IFace->getCategoryInstanceMethod(Sel); if (Getter) { // Check if we can reference this property. if (DiagnoseUseOfDecl(Getter, MemberLoc)) @@ -1513,9 +1454,6 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // methods. Setter = IFace->lookupPrivateMethod(SetterSel); } - // Look through local category implementations associated with the class. - if (!Setter) - Setter = IFace->getCategoryInstanceMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); @@ -2010,7 +1948,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // If we have an implementation in scope, check "private" methods. if (!Method) - Method = LookupPrivateClassMethod(Sel, Class); + Method = Class->lookupPrivateClassMethod(Sel); if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); @@ -2207,7 +2145,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, Method = ClassDecl->lookupClassMethod(Sel); if (!Method) - Method = LookupPrivateClassMethod(Sel, ClassDecl); + Method = ClassDecl->lookupPrivateClassMethod(Sel); } if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); @@ -2280,7 +2218,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!Method) { // If we have implementations in scope, check "private" methods. - Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + Method = ClassDecl->lookupPrivateMethod(Sel); if (!Method && getLangOpts().ObjCAutoRefCount) { Diag(Loc, diag::err_arc_may_not_respond) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 9affe9823a..4612930d45 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1481,7 +1481,7 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { // If there's an interface, look in both the public and private APIs. if (iface) { method = iface->lookupInstanceMethod(selector); - if (!method) method = LookupPrivateInstanceMethod(selector, iface); + if (!method) method = iface->lookupPrivateMethod(selector); } // Also check protocol qualifiers. diff --git a/test/SemaObjC/getter-setter-defined-in-category-of-parent.m b/test/SemaObjC/getter-setter-defined-in-category-of-parent.m new file mode 100644 index 0000000000..71c3237425 --- /dev/null +++ b/test/SemaObjC/getter-setter-defined-in-category-of-parent.m @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s + +@interface MyParent { + int X; +} +@end +@implementation MyParent +@end + +@interface MyParent(AA) { +} +@end +@implementation MyParent (AA) +- (void) setX: (int)in {X = in - 2;} +- (int) X {return X;} +@end + +@interface MyClass : MyParent +@end +@implementation MyClass +@end + +int foo(MyClass *o) { + o.X = 2; + return o.X; +} \ No newline at end of file diff --git a/test/SemaObjC/property-impl-misuse.m b/test/SemaObjC/property-impl-misuse.m index a5e1dd6b90..939909e9b2 100644 --- a/test/SemaObjC/property-impl-misuse.m +++ b/test/SemaObjC/property-impl-misuse.m @@ -30,8 +30,8 @@ @synthesize gradientStyle = _gradientStyle; - (void)setGradientStyle:(id)value { } -+ (void)_componentCellWithRepresentedObject { - self.gradientStyle; // expected-error {{property 'gradientStyle' not found on object of type 'Class'}} ++ (id)_componentCellWithRepresentedObject { + return self.gradientStyle; } @end