зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
8b0fa5241a
Коммит
0f9b18ed04
|
@ -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
|
||||
|
|
|
@ -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);
|
Загрузка…
Ссылка в новой задаче