From b0f245ccce94a069c9334e51f3c5d502eb2d0215 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 6 Apr 2012 19:47:36 +0000 Subject: [PATCH] modern objective-c translator: translate array literal expressions. // rdar://10803676 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154196 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Rewrite/RewriteModernObjC.cpp | 82 +++++++++++++++---- test/Rewriter/rewrite-modern-array-literal.mm | 27 ++++++ 2 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 test/Rewriter/rewrite-modern-array-literal.mm diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp index e160f0f434..0c57ae0812 100644 --- a/lib/Rewrite/RewriteModernObjC.cpp +++ b/lib/Rewrite/RewriteModernObjC.cpp @@ -2608,6 +2608,48 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { SourceLocation StartLoc = Exp->getLocStart(); SourceLocation EndLoc = Exp->getLocEnd(); + // Build the expression: __NSArray_literal(int, ...).arr + QualType IntQT = Context->IntTy; + QualType NSArrayFType = + getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); + std::string NSArrayFName("__NSArray_literal"); + FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); + DeclRefExpr *NSArrayDRE = + new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue, + SourceLocation()); + + SmallVector InitExprs; + unsigned NumElements = Exp->getNumElements(); + unsigned UnsignedIntSize = + static_cast(Context->getTypeSize(Context->UnsignedIntTy)); + Expr *count = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + InitExprs.push_back(count); + for (unsigned i = 0; i < NumElements; i++) + InitExprs.push_back(Exp->getElement(i)); + Expr *NSArrayCallExpr = + new (Context) CallExpr(*Context, NSArrayDRE, &InitExprs[0], InitExprs.size(), + NSArrayFType, VK_LValue, SourceLocation()); + + FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), + &Context->Idents.get("arr"), + Context->getPointerType(Context->VoidPtrTy), 0, + /*BitWidth=*/0, /*Mutable=*/true, + /*HasInit=*/false); + MemberExpr *ArrayLiteralME = + new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD, + SourceLocation(), + ARRFD->getType(), VK_LValue, + OK_Ordinary); + QualType ConstIdT = Context->getObjCIdType().withConst(); + CStyleCastExpr * ArrayLiteralObjects = + NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(ConstIdT), + CK_BitCast, + ArrayLiteralME); + // Synthesize a call to objc_msgSend(). SmallVector MsgExprs; SmallVector ClsExprs; @@ -2642,22 +2684,14 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { StartLoc, EndLoc); MsgExprs.push_back(SelExp); - unsigned NumElements = Exp->getNumElements(); + // (const id [])objects + MsgExprs.push_back(ArrayLiteralObjects); - // FIXME. Incomplete. - InitListExpr *ILE = - new (Context) InitListExpr(*Context, SourceLocation(), - Exp->getElements(), NumElements, - SourceLocation()); - MsgExprs.push_back(ILE); - unsigned UnsignedIntSize = - static_cast(Context->getTypeSize(Context->UnsignedIntTy)); - - Expr *count = IntegerLiteral::Create(*Context, - llvm::APInt(UnsignedIntSize, NumElements), - Context->UnsignedIntTy, - SourceLocation()); - MsgExprs.push_back(count); + // (NSUInteger)cnt + Expr *cnt = IntegerLiteral::Create(*Context, + llvm::APInt(UnsignedIntSize, NumElements), + Context->UnsignedIntTy, SourceLocation()); + MsgExprs.push_back(cnt); SmallVector ArgTypes; @@ -5477,6 +5511,24 @@ void RewriteModernObjC::Initialize(ASTContext &context) { Preamble += "#define __block\n"; Preamble += "#define __weak\n"; } + + // Declarations required for modern objective-c array and dictionary literals. + Preamble += "\n#include \n"; + Preamble += "struct __NSArray_literal {\n"; + Preamble += " void * *arr;\n"; + Preamble += " __NSArray_literal (unsigned int count, ...) {\n"; + Preamble += "\tva_list marker;\n"; + Preamble += "\tva_start(marker, count);\n"; + Preamble += "\tarr = new void *[count];\n"; + Preamble += "\tfor (unsigned i = 0; i < count; i++)\n"; + Preamble += "\t arr[i] = va_arg(marker, void *);\n"; + Preamble += "\tva_end( marker );\n"; + Preamble += " };\n"; + Preamble += " ~__NSArray_literal() {\n"; + Preamble += "\tdelete[] arr;\n"; + Preamble += " }\n"; + Preamble += "};\n"; + // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long // as this avoids warning in any 64bit/32bit compilation model. Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; diff --git a/test/Rewriter/rewrite-modern-array-literal.mm b/test/Rewriter/rewrite-modern-array-literal.mm new file mode 100644 index 0000000000..208e646eb3 --- /dev/null +++ b/test/Rewriter/rewrite-modern-array-literal.mm @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -x objective-c++ -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// rdar://10803676 + +extern "C" void *sel_registerName(const char *); +@class NSString; + +@interface NSNumber ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithInt:(int)value; +@end + +typedef unsigned long NSUInteger; + +@interface NSArray ++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; +@end + +int i; +int main() { + NSArray *array = @[ @"Hello", @1234 ]; + if (i) { + NSArray *array = @[ @"Hello", @1234 ]; + } + NSArray *array1 = @[ @"Hello", @1234, @[ @"Hello", @1234 ] ]; +} + -- 2.40.0