From 426bb9c9008b9f042e8b882352a2070e5b39d08c Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 9 Sep 2013 19:59:59 +0000 Subject: [PATCH] Modern ObjectiveC translator. Fix translation of message sent to aggregate-valued methods. Fix visibility of trampoline type used in translation of such expressions. // rdar://14932320 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190341 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Rewrite/Frontend/RewriteModernObjC.cpp | 62 +++++++++------------- test/Rewriter/objc-modern-StretAPI-3.mm | 58 ++++++++++++++++++++ 2 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 test/Rewriter/objc-modern-StretAPI-3.mm diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp index 8915bc4893..19407bafd0 100644 --- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp @@ -411,7 +411,6 @@ namespace { SourceLocation EndLoc=SourceLocation()); Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, - QualType msgSendType, QualType returnType, SmallVectorImpl &ArgTypes, SmallVectorImpl &MsgExprs, @@ -3183,7 +3182,6 @@ void RewriteModernObjC::RewriteLineDirective(const Decl *D) { /// starting with receiver. /// Method - Method being rewritten. Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, - QualType msgSendType, QualType returnType, SmallVectorImpl &ArgTypes, SmallVectorImpl &MsgExprs, @@ -3199,6 +3197,7 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla std::string name = "__Stret"; name += utostr(stretCount); std::string str = "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n"; + str += "namespace {\n"; str += "struct "; str += name; str += " {\n\t"; str += name; @@ -3217,9 +3216,27 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla } str += ") {\n"; - str += "\t if (receiver == 0)\n"; + str += "\t unsigned size = sizeof("; + str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n"; + + str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n"; + + str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); + str += ")(void *)objc_msgSend)(receiver, sel"; + for (unsigned i = 2; i < ArgTypes.size(); i++) { + str += ", arg"; str += utostr(i); + } + // could be vararg. + for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { + str += ", arg"; str += utostr(i); + } + str+= ");\n"; + + str += "\t else if (receiver == 0)\n"; str += "\t memset((void*)&s, 0, sizeof(s));\n"; str += "\t else\n"; + + str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); str += ")(void *)objc_msgSend_stret)(receiver, sel"; for (unsigned i = 2; i < ArgTypes.size(); i++) { @@ -3229,12 +3246,13 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { str += ", arg"; str += utostr(i); } - str += ");\n"; + + str += "\t}\n"; str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy()); str += " s;\n"; - str += "};\n\n"; + str += "};\n};\n\n"; SourceLocation FunLocStart; if (CurFunctionDef) FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); @@ -3651,39 +3669,11 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // expression which dictate which one to envoke depending on size of // method's return type. - Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, - msgSendType, returnType, + Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, + returnType, ArgTypes, MsgExprs, Exp->getMethodDecl()); - - // Build sizeof(returnType) - UnaryExprOrTypeTraitExpr *sizeofExpr = - new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, - Context->getTrivialTypeSourceInfo(returnType), - Context->getSizeType(), SourceLocation(), - SourceLocation()); - // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) - // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. - // For X86 it is more complicated and some kind of target specific routine - // is needed to decide what to do. - unsigned IntSize = - static_cast(Context->getTypeSize(Context->IntTy)); - IntegerLiteral *limit = IntegerLiteral::Create(*Context, - llvm::APInt(IntSize, 8), - Context->IntTy, - SourceLocation()); - BinaryOperator *lessThanExpr = - new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, - VK_RValue, OK_Ordinary, SourceLocation(), - false); - // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) - ConditionalOperator *CondExpr = - new (Context) ConditionalOperator(lessThanExpr, - SourceLocation(), CE, - SourceLocation(), STCE, - returnType, VK_RValue, OK_Ordinary); - ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), - CondExpr); + ReplacingStmt = STCE; } // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. return ReplacingStmt; diff --git a/test/Rewriter/objc-modern-StretAPI-3.mm b/test/Rewriter/objc-modern-StretAPI-3.mm new file mode 100644 index 0000000000..3ada56e939 --- /dev/null +++ b/test/Rewriter/objc-modern-StretAPI-3.mm @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// rdar://14932320 + +extern "C" void *sel_registerName(const char *); +typedef unsigned long size_t; + +typedef struct { + unsigned long long x; + unsigned long long y; +} myPoint; + +typedef struct { + unsigned long long x; + unsigned long long y; +} allPoint; + +@interface Obj ++ (myPoint)foo; ++ (myPoint)foo : (int)Arg1 : (double)fArg; ++ (allPoint)fee; +@end + +@implementation Obj ++ (allPoint)fee { + allPoint a; + a.x = a.y = 3; + + return a; +} ++ (myPoint)foo { + myPoint r; + r.x = 1; + r.y = 2; + return r; +} + ++ (myPoint)foo : (int)Arg1 : (double)fArg { + myPoint r; + return r; +} +@end + +myPoint Ret_myPoint() { + return [Obj foo]; +} + +allPoint Ret_allPoint() { + return [Obj fee]; +} + +myPoint Ret_myPoint1(int i, double d) { + return [Obj foo:i:d]; +} + +myPoint Ret_myPoint2() { + return [Obj foo]; +} -- 2.40.0