diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-03-30 23:35:47 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-03-30 23:35:47 +0000 |
commit | 86cff6080ba1db907009885adb5c6c64007e8b48 (patch) | |
tree | 6e987783fd3f44e7f772b081a6a3e12079be36e1 /lib/Rewrite/RewriteModernObjC.cpp | |
parent | 34ebe1e1b0779bcea2f277bc6b4e9dd98bf70b7b (diff) |
modern objective-c translator: writing container
literals. wip. // rdar://10803676
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153784 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Rewrite/RewriteModernObjC.cpp')
-rw-r--r-- | lib/Rewrite/RewriteModernObjC.cpp | 110 |
1 files changed, 109 insertions, 1 deletions
diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp index bfd14bb55b..91e89d1759 100644 --- a/lib/Rewrite/RewriteModernObjC.cpp +++ b/lib/Rewrite/RewriteModernObjC.cpp @@ -319,6 +319,7 @@ namespace { Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); Stmt *RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp); + Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); @@ -2566,6 +2567,111 @@ Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp) return CE; } +Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { + // synthesize declaration of helper functions needed in this routine. + if (!SelGetUidFunctionDecl) + SynthSelGetUidFunctionDecl(); + // use objc_msgSend() for all. + if (!MsgSendFunctionDecl) + SynthMsgSendFunctionDecl(); + if (!GetClassFunctionDecl) + SynthGetClassFunctionDecl(); + + FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; + SourceLocation StartLoc = Exp->getLocStart(); + SourceLocation EndLoc = Exp->getLocEnd(); + + // Synthesize a call to objc_msgSend(). + SmallVector<Expr*, 32> MsgExprs; + SmallVector<Expr*, 4> ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + QualType expType = Exp->getType(); + + // Create a call to objc_getClass("NSArray"). It will be th 1st argument. + ObjCInterfaceDecl *Class = + expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface(); + + IdentifierInfo *clsName = Class->getIdentifier(); + ClsExprs.push_back(StringLiteral::Create(*Context, + clsName->getName(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(Cls); + + // Create a call to sel_registerName("arrayWithObjects:count:"). + // it will be the 2nd argument. + SmallVector<Expr*, 4> SelExprs; + ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod(); + SelExprs.push_back(StringLiteral::Create(*Context, + ArrayMethod->getSelector().getAsString(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, + &SelExprs[0], SelExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(SelExp); + + unsigned NumElements = Exp->getNumElements(); + + // FIXME. Incomplete. + InitListExpr *ILE = + new (Context) InitListExpr(*Context, SourceLocation(), + Exp->getElements(), NumElements, + SourceLocation()); + MsgExprs.push_back(ILE); + unsigned UnsignedIntSize = + static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); + + Expr *count = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, + SourceLocation()); + MsgExprs.push_back(count); + + + SmallVector<QualType, 4> ArgTypes; + ArgTypes.push_back(Context->getObjCIdType()); + ArgTypes.push_back(Context->getObjCSelType()); + for (ObjCMethodDecl::param_iterator PI = ArrayMethod->param_begin(), + E = ArrayMethod->param_end(); PI != E; ++PI) + ArgTypes.push_back((*PI)->getType()); + + QualType returnType = Exp->getType(); + // Get the type, we will need to reference it in a couple spots. + QualType msgSendType = MsgSendFlavor->getType(); + + // Create a reference to the objc_msgSend() declaration. + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, + VK_LValue, SourceLocation()); + + CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(Context->VoidTy), + CK_BitCast, DRE); + + // Now do the "normal" pointer to function cast. + QualType castType = + getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), + ArrayMethod->isVariadic()); + castType = Context->getPointerType(castType); + cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, + cast); + + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); + + const FunctionType *FT = msgSendType->getAs<FunctionType>(); + CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], + MsgExprs.size(), + FT->getResultType(), VK_RValue, + EndLoc); + ReplaceStmt(Exp, CE); + return CE; +} + // struct objc_super { struct objc_object *receiver; struct objc_class *super; }; QualType RewriteModernObjC::getSuperStructType() { if (!SuperStructDecl) { @@ -4861,7 +4967,9 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCNumericLiteral *NumericLitExpr = dyn_cast<ObjCNumericLiteral>(S)) return RewriteObjCNumericLiteralExpr(NumericLitExpr); - + + if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S)) + return RewriteObjCArrayLiteralExpr(ArrayLitExpr); if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { #if 0 |