diff options
-rw-r--r-- | include/clang/AST/DeclObjC.h | 6 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 72 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 2 | ||||
-rw-r--r-- | test/SemaObjC/getter-setter-defined-in-category-of-parent.m | 26 | ||||
-rw-r--r-- | test/SemaObjC/property-impl-misuse.m | 4 |
8 files changed, 59 insertions, 83 deletions
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 |