From: Fariborz Jahanian Date: Thu, 17 Jun 2010 19:56:20 +0000 (+0000) Subject: Objective-c++ IRGen. Support for @selector expression as X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03b2960c14aede6ac82bdef32247094ebb72fa69;p=clang Objective-c++ IRGen. Support for @selector expression as an lvalue. Fixes PR7390. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106235 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index e36ae41ce4..1d715b004d 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1194,6 +1194,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { case ObjCIsaExprClass: case StringLiteralClass: // C99 6.5.1p4 case ObjCEncodeExprClass: // @encode behaves like its string in every way. + case ObjCSelectorExprClass: // @selector return LV_Valid; case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2)))) // For vectors, make sure base is an lvalue (i.e. not a function call). diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 4b66ec277e..aab54099fd 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -568,6 +568,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { switch (E->getStmtClass()) { default: return EmitUnsupportedLValue(E, "l-value expression"); + case Expr::ObjCSelectorExprClass: + return EmitObjCSelectorLValue(cast(E)); case Expr::ObjCIsaExprClass: return EmitObjCIsaExpr(cast(E)); case Expr::BinaryOperatorClass: @@ -1977,6 +1979,12 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } +LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) { + llvm::Value *V = + CGM.getObjCRuntime().GetSelector(Builder, E->getSelector(), true); + return LValue::MakeAddr(V, MakeQualifiers(E->getType())); +} + llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) { return CGM.getObjCRuntime().EmitIvarOffset(*this, Interface, Ivar); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 81b038bdf1..0835e52b52 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -162,7 +162,8 @@ public: const ObjCMethodDecl *Method); virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *OID); - virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, + bool lval = false); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method); @@ -360,14 +361,16 @@ llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, return Builder.CreateCall(ClassLookupFn, ClassName); } -llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { +llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel, + bool lval) { llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; if (US == 0) US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), llvm::GlobalValue::PrivateLinkage, ".objc_untyped_selector_alias"+Sel.getAsString(), NULL, &TheModule); - + if (lval) + return US; return Builder.CreateLoad(US); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 24c7511a51..8374aa8c55 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1129,7 +1129,8 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. - llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); + llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel, + bool lval=false); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1160,7 +1161,8 @@ public: virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); - virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, + bool lval = false); /// The NeXT/Apple runtimes do not support typed selectors; just emit an /// untyped one. @@ -1328,7 +1330,8 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. - llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); + llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel, + bool lval=false); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -1391,8 +1394,9 @@ public: virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); - virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) - { return EmitSelector(Builder, Sel); } + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, + bool lvalue = false) + { return EmitSelector(Builder, Sel, lvalue); } /// The NeXT/Apple runtimes do not support typed selectors; just emit an /// untyped one. @@ -1492,8 +1496,9 @@ llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder, } /// GetSelector - Return the pointer to the unique'd string for this selector. -llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { - return EmitSelector(Builder, Sel); +llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel, + bool lval) { + return EmitSelector(Builder, Sel, lval); } llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method) { @@ -3107,7 +3112,8 @@ llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, return Builder.CreateLoad(Entry, "tmp"); } -llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { +llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel, + bool lvalue) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; if (!Entry) { @@ -3120,6 +3126,8 @@ llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { 4, true); } + if (lvalue) + return Entry; return Builder.CreateLoad(Entry, "tmp"); } @@ -5408,7 +5416,7 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, } llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, - Selector Sel) { + Selector Sel, bool lval) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; if (!Entry) { @@ -5423,6 +5431,8 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, CGM.AddUsedGlobal(Entry); } + if (lval) + return Entry; return Builder.CreateLoad(Entry, "tmp"); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 1f6d63b8ab..28c77c61b5 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -97,7 +97,7 @@ public: /// return value should have the LLVM type for pointer-to /// ASTContext::getObjCSelType(). virtual llvm::Value *GetSelector(CGBuilderTy &Builder, - Selector Sel) = 0; + Selector Sel, bool lval=false) = 0; /// Get a typed selector. virtual llvm::Value *GetSelector(CGBuilderTy &Builder, diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f8ca34c614..f2a35ac5c7 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1087,6 +1087,7 @@ public: LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E); LValue EmitStmtExprLValue(const StmtExpr *E); LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); + LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E); //===--------------------------------------------------------------------===// // Scalar Expression Emission diff --git a/test/CodeGenObjCXX/selactor-expr-lvalue.mm b/test/CodeGenObjCXX/selactor-expr-lvalue.mm new file mode 100644 index 0000000000..69b82e92f2 --- /dev/null +++ b/test/CodeGenObjCXX/selactor-expr-lvalue.mm @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s +// PR7390 + +@interface NSObject {} +- (void)respondsToSelector:(SEL&)s : (SEL*)s1; +- (void) setPriority:(int)p; +- (void)Meth; +@end + +@implementation NSObject +- (void)Meth { + [self respondsToSelector:@selector(setPriority:) : &@selector(setPriority:)]; +} +- (void) setPriority:(int)p{} +- (void)respondsToSelector:(SEL&)s : (SEL*)s1 {} +@end