From: Steve Naroff Date: Tue, 2 Oct 2007 20:01:56 +0000 (+0000) Subject: - Add ObjcInterfaceDecl::lookupInstanceMethod(), lookupClassMethod(). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a8a9a41e9067b708498c02180159bafecfa044f;p=clang - Add ObjcInterfaceDecl::lookupInstanceMethod(), lookupClassMethod(). - Add ObjcMessageExpr::getSelector(), getClassName(). - Change Sema::getObjCInterfaceDecl() to simply take an IdentifierInfo (no Scope needed). - Remove FIXME for printing ObjCMessageExpr's. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42543 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Decl.cpp b/AST/Decl.cpp index d23f3cb6f3..9e02607cf3 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -408,4 +408,36 @@ void ObjcImplementationDecl::ObjcAddImplMethods(ObjcMethodDecl **insMethods, } } +// FIXME: look through categories... +ObjcMethodDecl *ObjcInterfaceDecl::lookupInstanceMethod(Selector &Sel) { + ObjcInterfaceDecl* ClassDecl = this; + while (ClassDecl != NULL) { + ObjcMethodDecl **methods = ClassDecl->getInsMethods(); + int methodCount = ClassDecl->getNumInsMethods(); + for (int i = 0; i < methodCount; ++i) { + if (methods[i]->getSelector() == Sel) { + return methods[i]; + } + } + ClassDecl = ClassDecl->getSuperClass(); + } + return NULL; +} + +// FIXME: look through categories... +ObjcMethodDecl *ObjcInterfaceDecl::lookupClassMethod(Selector &Sel) { + ObjcInterfaceDecl* ClassDecl = this; + while (ClassDecl != NULL) { + ObjcMethodDecl **methods = ClassDecl->getClsMethods(); + int methodCount = ClassDecl->getNumClsMethods(); + for (int i = 0; i < methodCount; ++i) { + if (methods[i]->getSelector() == Sel) { + return methods[i]; + } + } + ClassDecl = ClassDecl->getSuperClass(); + } + return NULL; +} + diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp index f878ca8137..a25d8eee4a 100644 --- a/AST/StmtPrinter.cpp +++ b/AST/StmtPrinter.cpp @@ -614,10 +614,17 @@ void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { OS << "["; - PrintExpr(Mess->getReceiver()); - for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) { - // FIXME: get/print keyword... - PrintExpr(Mess->getArg(i)); + Expr *receiver = Mess->getReceiver(); + if (receiver) PrintExpr(receiver); + else OS << Mess->getClassName()->getName(); + Selector &selector = Mess->getSelector(); + if (selector.isUnarySelector()) { + OS << " " << selector.getIdentifierInfoForSlot(0)->getName(); + } else { + for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) { + OS << " " << selector.getIdentifierInfoForSlot(i)->getName() << ":"; + PrintExpr(Mess->getArg(i)); + } } OS << "]"; } diff --git a/Sema/Sema.h b/Sema/Sema.h index 74f79d4f3f..a965f7f725 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -187,8 +187,7 @@ private: Scope *FnBodyScope); ScopedDecl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc, Scope *S); - ObjcInterfaceDecl *getObjCInterfaceDecl(Scope *S, - IdentifierInfo *Id, SourceLocation IdLoc); + ObjcInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id); ObjcProtocolDecl *getObjCProtocolDecl(Scope *S, IdentifierInfo *Id, SourceLocation IdLoc); ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S); @@ -436,7 +435,7 @@ public: // is obtained from Sel.getNumArgs(). virtual ExprResult ActOnClassMessage( IdentifierInfo *receivingClassName, Selector Sel, - SourceLocation lbrac, SourceLocation rbrac, ExprTy **ArgExprs); + SourceLocation lbrac, SourceLocation rbrac, ExprTy **ArgExprs); // ActOnInstanceMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 7b5aba390b..ed8591ddca 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -80,11 +80,18 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) { /// getObjcInterfaceDecl - Look up a for a class declaration in the scope. /// return 0 if one not found. -ObjcInterfaceDecl *Sema::getObjCInterfaceDecl(Scope *S, - IdentifierInfo *Id, - SourceLocation IdLoc) { - ScopedDecl *IdDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, - IdLoc, S); +ObjcInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) { + + // Scan up the scope chain looking for a decl that matches this identifier + // that is in the appropriate namespace. This search should not take long, as + // shadowing of names is uncommon, and deep shadowing is extremely uncommon. + ScopedDecl *IdDecl = NULL; + for (ScopedDecl *D = Id->getFETokenInfo(); D; D = D->getNext()) { + if (D->getIdentifierNamespace() == Decl::IDNS_Ordinary) { + IdDecl = D; + break; + } + } if (IdDecl && !isa(IdDecl)) IdDecl = 0; return cast_or_null(static_cast(IdDecl)); @@ -905,7 +912,7 @@ Sema::DeclTy *Sema::ObjcStartClassInterface(Scope* S, Diag(PrevDecl->getLocation(), diag::err_previous_definition); } - ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc); + ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(ClassName); if (IDecl) { // Class already seen. Is it a forward declaration? if (!IDecl->getIsForwardDecl()) @@ -936,7 +943,7 @@ Sema::DeclTy *Sema::ObjcStartClassInterface(Scope* S, } else { // Check that super class is previously defined - SuperClassEntry = getObjCInterfaceDecl(S, SuperName, SuperLoc); + SuperClassEntry = getObjCInterfaceDecl(SuperName); if (!SuperClassEntry || SuperClassEntry->getIsForwardDecl()) { Diag(AtInterfaceLoc, diag::err_undef_superclass, SuperName->getName(), @@ -1030,7 +1037,7 @@ Sema::DeclTy *Sema::ObjcStartCatInterface(Scope* S, IdentifierInfo *CategoryName, SourceLocation CategoryLoc, IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { ObjcCategoryDecl *CDecl; - ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc); + ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(ClassName); CDecl = new ObjcCategoryDecl(AtInterfaceLoc, NumProtoRefs); CDecl->setClassInterface(IDecl); @@ -1075,7 +1082,7 @@ Sema::DeclTy *Sema::ObjcStartCategoryImplementation(Scope* S, SourceLocation AtCatImplLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc) { - ObjcInterfaceDecl *IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc); + ObjcInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName); ObjcCategoryImplDecl *CDecl = new ObjcCategoryImplDecl(AtCatImplLoc, ClassName, IDecl, CatName); @@ -1103,7 +1110,7 @@ Sema::DeclTy *Sema::ObjcStartClassImplementation(Scope *S, } else { // Is there an interface declaration of this class; if not, warn! - IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc); + IDecl = getObjCInterfaceDecl(ClassName); if (!IDecl) Diag(ClassLoc, diag::warn_undef_interface, ClassName->getName()); } @@ -1121,7 +1128,7 @@ Sema::DeclTy *Sema::ObjcStartClassImplementation(Scope *S, Diag(PrevDecl->getLocation(), diag::err_previous_definition); } else { - SDecl = getObjCInterfaceDecl(S, SuperClassname, SuperClassLoc); + SDecl = getObjCInterfaceDecl(SuperClassname); if (!SDecl) Diag(SuperClassLoc, diag::err_undef_superclass, SuperClassname->getName(), ClassName->getName()); @@ -1330,7 +1337,7 @@ Sema::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, for (unsigned i = 0; i != NumElts; ++i) { ObjcInterfaceDecl *IDecl; - IDecl = getObjCInterfaceDecl(S, IdentList[i], AtClassLoc); + IDecl = getObjCInterfaceDecl(IdentList[i]); if (!IDecl) {// Already seen? IDecl = new ObjcInterfaceDecl(SourceLocation(), 0, IdentList[i], true); // Chain & install the interface decl into the identifier. @@ -1655,8 +1662,7 @@ void Sema::ActOnFields(Scope* S, cast(static_cast(RecDecl)); assert(IMPDecl && "ActOnFields - missing ObjcImplementationDecl"); IMPDecl->ObjcAddInstanceVariablesToClassImpl(ClsFields, RecFields.size()); - ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(S, - IMPDecl->getIdentifier(), RecLoc); + ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(IMPDecl->getIdentifier()); if (IDecl) ActOnImpleIvarVsClassIvars(static_cast(IDecl), reinterpret_cast(&RecFields[0]), RecFields.size()); @@ -1705,8 +1711,7 @@ void Sema::ObjcAddMethodsToClass(Scope* S, DeclTy *ClassDecl, static_cast(ClassDecl)); ImplClass->ObjcAddImplMethods(&insMethods[0], insMethods.size(), &clsMethods[0], clsMethods.size()); - ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(S, - ImplClass->getIdentifier(), SourceLocation()); + ObjcInterfaceDecl* IDecl = getObjCInterfaceDecl(ImplClass->getIdentifier()); if (IDecl) ImplMethodsVsClassMethods(ImplClass, IDecl); } diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 0041805dfb..29f422c04a 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -14,6 +14,7 @@ #include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/Parse/DeclSpec.h" #include "clang/Lex/Preprocessor.h" @@ -1875,14 +1876,18 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). Sema::ExprResult Sema::ActOnClassMessage( - IdentifierInfo *receivingClassName, Selector Sel, + IdentifierInfo *receiverName, Selector Sel, SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args) { - assert(receivingClassName && "missing receiver class name"); + assert(receiverName && "missing receiver class name"); + ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName); + ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel); + assert(Method && "missing method declaration"); + QualType retType = Method->getMethodType(); + // Expr *RExpr = global reference to the class symbol... Expr **ArgExprs = reinterpret_cast(Args); - return new ObjCMessageExpr(receivingClassName, Sel, - Context.IntTy/*FIXME*/, lbrac, rbrac, ArgExprs); + return new ObjCMessageExpr(receiverName, Sel, retType, lbrac, rbrac, ArgExprs); } // ActOnInstanceMessage - used for both unary and keyword messages. @@ -1895,7 +1900,19 @@ Sema::ExprResult Sema::ActOnInstanceMessage( assert(receiver && "missing receiver expression"); Expr *RExpr = static_cast(receiver); + // FIXME (snaroff): checking in this code from Patrick. Needs to be revisited. + // how do we get the ClassDecl from the receiver expression? + QualType receiverType = RExpr->getType(); + while (receiverType->isPointerType()) { + PointerType *pointerType = static_cast(receiverType.getTypePtr()); + receiverType = pointerType->getPointeeType(); + } + assert(ObjcInterfaceType::classof(receiverType.getTypePtr()) && "bad receiver type"); + ObjcInterfaceDecl* ClassDecl = static_cast( + receiverType.getTypePtr())->getDecl(); + ObjcMethodDecl *Method = ClassDecl->lookupInstanceMethod(Sel); + assert(Method && "missing method declaration"); + QualType returnType = Method->getMethodType(); Expr **ArgExprs = reinterpret_cast(Args); - return new ObjCMessageExpr(RExpr, Sel, - Context.IntTy/*FIXME*/, lbrac, rbrac, ArgExprs); + return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs); } diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 6389e5fbc4..314ed3ea3c 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -737,7 +737,6 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; - compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 615bf454de..6099e56d7c 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -127,6 +127,8 @@ public: void setListCategories(ObjcCategoryDecl *category) { ListCategories = category; } + ObjcMethodDecl *lookupInstanceMethod(Selector &Sel); + ObjcMethodDecl *lookupClassMethod(Selector &Sel); static bool classof(const Decl *D) { return D->getKind() == ObjcInterface; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0a0e685f80..d260cb7193 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1100,6 +1100,12 @@ public: const Expr *getReceiver() const { return SubExprs[RECEIVER]; } Expr *getReceiver() { return SubExprs[RECEIVER]; } + const Selector &getSelector() const { return SelName; } + Selector &getSelector() { return SelName; } + + const IdentifierInfo *getClassName() const { return ClassName; } + IdentifierInfo *getClassName() { return ClassName; } + /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return SelName.getNumArgs(); }