diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-03-30 16:49:36 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-03-30 16:49:36 +0000 |
commit | 0f9b18ed048cd5c1ebe786d1dee05577e84d0c27 (patch) | |
tree | a341830a86d16c8c629cdf3d7df26dd14001696a | |
parent | 8b0fa5241a0416fc50dfbb7e38f20e777f191848 (diff) |
modern objective-c translator: writing numeric
literals. // rdar://10803676
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153756 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Rewrite/RewriteModernObjC.cpp | 104 | ||||
-rw-r--r-- | test/Rewriter/objc-modern-numeric-literal.mm | 69 |
2 files changed, 173 insertions, 0 deletions
diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp index ec7089af57..bfd14bb55b 100644 --- a/lib/Rewrite/RewriteModernObjC.cpp +++ b/lib/Rewrite/RewriteModernObjC.cpp @@ -318,6 +318,7 @@ namespace { Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); + Stmt *RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); @@ -2466,6 +2467,105 @@ Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) { return PE; } +Stmt *RewriteModernObjC::RewriteObjCNumericLiteralExpr(ObjCNumericLiteral *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*, 4> MsgExprs; + SmallVector<Expr*, 4> ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + QualType expType = Exp->getType(); + + // Create a call to objc_getClass("NSNumber"). 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("numberWithBool:"), etc. + // it will be the 2nd argument. + SmallVector<Expr*, 4> SelExprs; + ObjCMethodDecl *NumericMethod = Exp->getObjCNumericLiteralMethod(); + SelExprs.push_back(StringLiteral::Create(*Context, + NumericMethod->getSelector().getAsString(), + StringLiteral::Ascii, false, + argType, SourceLocation())); + CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, + &SelExprs[0], SelExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(SelExp); + + // User provided numeric literal is the 3rd, and last, argument. + Expr *userExpr = Exp->getNumber(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { + QualType type = ICE->getType(); + const Expr *SubExpr = ICE->IgnoreParenImpCasts(); + CastKind CK = CK_BitCast; + if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) + CK = CK_IntegralToBoolean; + userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); + } + MsgExprs.push_back(userExpr); + + SmallVector<QualType, 4> ArgTypes; + ArgTypes.push_back(Context->getObjCIdType()); + ArgTypes.push_back(Context->getObjCSelType()); + for (ObjCMethodDecl::param_iterator PI = NumericMethod->param_begin(), + E = NumericMethod->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(), + NumericMethod->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) { @@ -4758,6 +4858,10 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S)) return RewriteObjCBoolLiteralExpr(BoolLitExpr); + + if (ObjCNumericLiteral *NumericLitExpr = dyn_cast<ObjCNumericLiteral>(S)) + return RewriteObjCNumericLiteralExpr(NumericLitExpr); + if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { #if 0 diff --git a/test/Rewriter/objc-modern-numeric-literal.mm b/test/Rewriter/objc-modern-numeric-literal.mm new file mode 100644 index 0000000000..d27d03d54e --- /dev/null +++ b/test/Rewriter/objc-modern-numeric-literal.mm @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -E %s -o %t.mm +// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o - | FileCheck %s +// rdar://10803676 + +extern "C" void *sel_registerName(const char *); + +typedef signed char BOOL; +typedef long NSInteger; +typedef unsigned long NSUInteger; + +#if __has_feature(objc_bool) +#define YES __objc_yes +#define NO __objc_no +#else +#define YES ((BOOL)1) +#define NO ((BOOL)0) +#endif + +@interface NSNumber ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; ++ (NSNumber *)numberWithInteger:(NSInteger)value ; ++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ; +@end + +int main(int argc, const char *argv[]) { + // character literals. + NSNumber *theLetterZ = @'Z'; // equivalent to [NSNumber numberWithChar:'Z'] + + // integral literals. + NSNumber *fortyTwo = @42; // equivalent to [NSNumber numberWithInt:42] + NSNumber *fortyTwoUnsigned = @42U; // equivalent to [NSNumber numberWithUnsignedInt:42U] + NSNumber *fortyTwoLong = @42L; // equivalent to [NSNumber numberWithLong:42L] + NSNumber *fortyTwoLongLong = @42LL; // equivalent to [NSNumber numberWithLongLong:42LL] + + // floating point literals. + NSNumber *piFloat = @3.141592654F; // equivalent to [NSNumber numberWithFloat:3.141592654F] + NSNumber *piDouble = @3.1415926535; // equivalent to [NSNumber numberWithDouble:3.1415926535] + + // BOOL literals. + NSNumber *yesNumber = @YES; // equivalent to [NSNumber numberWithBool:YES] + NSNumber *noNumber = @NO; // equivalent to [NSNumber numberWithBool:NO] + + NSNumber *trueNumber = @true; // equivalent to [NSNumber numberWithBool:(BOOL)true] + NSNumber *falseNumber = @false; // equivalent to [NSNumber numberWithBool:(BOOL)false] +} + +// CHECK: NSNumber *theLetterZ = ((NSNumber *(*)(id, SEL, char))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithChar:"), 'Z'); +// CHECK: NSNumber *fortyTwo = ((NSNumber *(*)(id, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), 42); +// CHECK: NSNumber *fortyTwoUnsigned = ((NSNumber *(*)(id, SEL, unsigned int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithUnsignedInt:"), 42U); +// CHECK: NSNumber *fortyTwoLong = ((NSNumber *(*)(id, SEL, long))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithLong:"), 42L); +// CHECK: NSNumber *fortyTwoLongLong = ((NSNumber *(*)(id, SEL, long long))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithLongLong:"), 42LL); +// CHECK: NSNumber *piFloat = ((NSNumber *(*)(id, SEL, float))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithFloat:"), 3.1415927); +// CHECK: NSNumber *piDouble = ((NSNumber *(*)(id, SEL, double))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithDouble:"), 3.1415926535); +// CHECK: NSNumber *yesNumber = ((NSNumber *(*)(id, SEL, BOOL))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithBool:"), (BOOL)true); +// CHECK: NSNumber *noNumber = ((NSNumber *(*)(id, SEL, BOOL))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithBool:"), (BOOL)false); +// CHECK: NSNumber *trueNumber = ((NSNumber *(*)(id, SEL, BOOL))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithBool:"), (BOOL)true); +// CHECK: NSNumber *falseNumber = ((NSNumber *(*)(id, SEL, BOOL))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithBool:"), (BOOL)false); |