diff options
author | Steve Naroff <snaroff@apple.com> | 2009-02-23 02:25:40 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-02-23 02:25:40 +0000 |
commit | d526c2f2ef28643c15589135b59eb4a8d9f9414c (patch) | |
tree | 4c5b36b23637075ff1f83caf0f5939a74849a6ab /lib/Sema/SemaExprObjC.cpp | |
parent | d3d4f57f3562490ca825a387332d9fabc6281307 (diff) |
Sema::ActOnInstanceMessage(): Tighen up the lookup rules for handling messages to 'Class'. Also improve "super" handling.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65300 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index a593549235..d6bec76276 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -309,6 +309,22 @@ Sema::ExprResult Sema::ActOnClassMessage( lbrac, rbrac, ArgExprs, NumArgs); } +// This routine makes sure we handle the following: +// +// [(Object <Func> *)super class_func0]; +// [(id <Func>)super class_func0]; +// +static bool isSuperExpr(Stmt *S) { + for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); + CI != E; ++CI) { + if (*CI) + return isSuperExpr(*CI); + } + if (isa<ObjCSuperExpr>(S)) + return true; + return false; +} + // ActOnInstanceMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). @@ -327,7 +343,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, Context.getCanonicalType(RExpr->getType()).getUnqualifiedType(); // Handle messages to 'super'. - if (isa<ObjCSuperExpr>(RExpr)) { + if (isSuperExpr(RExpr)) { ObjCMethodDecl *Method = 0; if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { // If we have an interface in scope, check 'super' methods. @@ -364,17 +380,23 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { ObjCMethodDecl *Method = 0; if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { - // If we have an implementation in scope, check "private" methods. - if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) - if (ObjCImplementationDecl *ImpDecl = - ObjCImplementations[ClassDecl->getIdentifier()]) - Method = ImpDecl->getClassMethod(Sel); - + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // 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 && DiagnoseUseOfDecl(Method, receiverLoc)) return true; - } - if (!Method) + } else { + // We're not in a method context, look for any factory method named 'Sel'. Method = FactoryMethodPool[Sel].Method; + } if (!Method) Method = LookupInstanceMethodInGlobalPool( Sel, SourceRange(lbrac,rbrac)); |