зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
2850784bda
Коммит
f1afaf6fe2
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче