Skip to content
Snippets Groups Projects
Commit b162f170 authored by Steve Naroff's avatar Steve Naroff
Browse files

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.

llvm-svn: 65532
parent d7b8508d
No related branches found
No related tags found
No related merge requests found
...@@ -1683,6 +1683,11 @@ public: ...@@ -1683,6 +1683,11 @@ public:
AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
bool isVariadic = false); 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. // ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions // ArgExprs is optional - if it is present, the number of expressions
// is obtained from NumArgs. // is obtained from NumArgs.
......
...@@ -202,6 +202,27 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, ...@@ -202,6 +202,27 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
return anyIncompatibleArgs; 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. // ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions // ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs(). // is obtained from Sel.getNumArgs().
...@@ -282,19 +303,9 @@ Sema::ExprResult Sema::ActOnClassMessage( ...@@ -282,19 +303,9 @@ Sema::ExprResult Sema::ActOnClassMessage(
Method = ClassDecl->lookupClassMethod(Sel); Method = ClassDecl->lookupClassMethod(Sel);
// If we have an implementation in scope, check "private" methods. // If we have an implementation in scope, check "private" methods.
if (!Method) { if (!Method)
if (ObjCImplementationDecl *ImpDecl = Method = LookupPrivateMethod(Sel, ClassDecl);
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);
}
}
}
// Before we give up, check if the selector is an instance method. // Before we give up, check if the selector is an instance method.
if (!Method) if (!Method)
Method = ClassDecl->lookupInstanceMethod(Sel); Method = ClassDecl->lookupInstanceMethod(Sel);
...@@ -379,12 +390,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, ...@@ -379,12 +390,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// First check the public methods in the class interface. // First check the public methods in the class interface.
Method = ClassDecl->lookupClassMethod(Sel); Method = ClassDecl->lookupClassMethod(Sel);
if (!Method) { if (!Method)
// If we have an implementation in scope, check "private" methods. Method = LookupPrivateMethod(Sel, ClassDecl);
if (ObjCImplementationDecl *ImpDecl =
ObjCImplementations[ClassDecl->getIdentifier()])
Method = ImpDecl->getClassMethod(Sel);
}
} }
if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true; return true;
......
// 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment