[cfe-commits] r156844 - in /cfe/trunk: lib/Edit/RewriteObjCFoundationAPI.cpp test/ARCMT/objcmt-boxing.m test/ARCMT/objcmt-boxing.m.result test/ARCMT/objcmt-numeric-literals.m.result

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue May 15 12:17:50 PDT 2012


Author: akirtzidis
Date: Tue May 15 14:17:49 2012
New Revision: 156844

URL: http://llvm.org/viewvc/llvm-project?rev=156844&view=rev
Log:
[objcmt] Rewrite [NSNumber numberWith*] messages to the new @() boxing syntax.

There are some caveats:
-If an implicit cast (e.g. int -> float for numberWithFloat:) was required, the message
 will not get rewritten
-If the message was with numberWithInteger:/numberWithUnsignedInteger:, which are very
 commonly used, be more liberal and allow the boxing syntax if the underlying type has
 same signedness and will not lose precision.

Part of rdar://11438360

Added:
    cfe/trunk/test/ARCMT/objcmt-boxing.m
    cfe/trunk/test/ARCMT/objcmt-boxing.m.result
Modified:
    cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp
    cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result

Modified: cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp?rev=156844&r1=156843&r2=156844&view=diff
==============================================================================
--- cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp (original)
+++ cfe/trunk/lib/Edit/RewriteObjCFoundationAPI.cpp Tue May 15 14:17:49 2012
@@ -209,6 +209,8 @@
                                   const NSAPI &NS, Commit &commit);
 static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
                                   const NSAPI &NS, Commit &commit);
+static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
+                                            const NSAPI &NS, Commit &commit);
 
 bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
                                       const NSAPI &NS, Commit &commit) {
@@ -372,7 +374,7 @@
     return true;
   }
 
-  return false;
+  return rewriteToNumericBoxedExpression(Msg, NS, commit);
 }
 
 static bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg,
@@ -386,7 +388,7 @@
     return true;
   }
 
-  return false;
+  return rewriteToNumericBoxedExpression(Msg, NS, commit);
 }
 
 namespace {
@@ -488,10 +490,10 @@
       literalE = UOE->getSubExpr();
   }
 
-  // Only integer and floating literals; non-literals or imaginary literal
-  // cannot be rewritten.
+  // Only integer and floating literals, otherwise try to rewrite to boxed
+  // expression.
   if (!isa<IntegerLiteral>(literalE) && !isa<FloatingLiteral>(literalE))
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
 
   ASTContext &Ctx = NS.getASTContext();
   Selector Sel = Msg->getSelector();
@@ -511,7 +513,7 @@
   case NSAPI::NSNumberWithShort:
   case NSAPI::NSNumberWithUnsignedShort:
   case NSAPI::NSNumberWithBool:
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
 
   case NSAPI::NSNumberWithUnsignedInt:
   case NSAPI::NSNumberWithUnsignedInteger:
@@ -551,15 +553,16 @@
   }
 
   // We will need to modify the literal suffix to get the same type as the call.
-  // Don't even try if it came from a macro.
+  // Try with boxed expression if it came from a macro.
   if (ArgRange.getBegin().isMacroID())
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
 
   bool LitIsFloat = ArgTy->isFloatingType();
-  // For a float passed to integer call, don't try rewriting. It is difficult
-  // and a very uncommon case anyway.
+  // For a float passed to integer call, don't try rewriting to objc literal.
+  // It is difficult and a very uncommon case anyway.
+  // But try with boxed expression.
   if (LitIsFloat && !CallIsFloating)
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
 
   // Try to modify the literal make it the same type as the method call.
   // -Modify the suffix, and/or
@@ -570,11 +573,11 @@
   if (const IntegerLiteral *IntE = dyn_cast<IntegerLiteral>(literalE))
     isIntZero = !IntE->getValue().getBoolValue();
   if (!getLiteralInfo(ArgRange, LitIsFloat, isIntZero, Ctx, LitInfo))
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
 
   // Not easy to do int -> float with hex/octal and uncommon anyway.
   if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal))
-    return false;
+    return rewriteToNumericBoxedExpression(Msg, NS, commit);
   
   SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin();
   SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd();
@@ -672,3 +675,128 @@
     commit.insertWrap("(", Range, ")");
   commit.insertBefore(Range.getBegin(), "(id)");
 }
+
+//===----------------------------------------------------------------------===//
+// rewriteToNumericBoxedExpression.
+//===----------------------------------------------------------------------===//
+
+static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
+                                            const NSAPI &NS, Commit &commit) {
+  if (Msg->getNumArgs() != 1)
+    return false;
+
+  const Expr *Arg = Msg->getArg(0);
+  if (Arg->isTypeDependent())
+    return false;
+
+  ASTContext &Ctx = NS.getASTContext();
+  Selector Sel = Msg->getSelector();
+  llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
+    MKOpt = NS.getNSNumberLiteralMethodKind(Sel);
+  if (!MKOpt)
+    return false;
+  NSAPI::NSNumberLiteralMethodKind MK = *MKOpt;
+
+  const Expr *OrigArg = Arg->IgnoreImpCasts();
+  QualType FinalTy = Arg->getType();
+  QualType OrigTy = OrigArg->getType();
+  uint64_t FinalTySize = Ctx.getTypeSize(FinalTy);
+  uint64_t OrigTySize = Ctx.getTypeSize(OrigTy);
+
+  bool isTruncated = FinalTySize < OrigTySize; 
+  bool needsCast = false;
+
+  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+    switch (ICE->getCastKind()) {
+    case CK_LValueToRValue:
+    case CK_NoOp:
+    case CK_UserDefinedConversion:
+      break;
+
+    case CK_IntegralCast: {
+      if (MK == NSAPI::NSNumberWithBool && OrigTy->isBooleanType())
+        break;
+      // Be more liberal with Integer/UnsignedInteger which are very commonly
+      // used.
+      if ((MK == NSAPI::NSNumberWithInteger ||
+           MK == NSAPI::NSNumberWithUnsignedInteger) &&
+          !isTruncated) {
+        if (OrigTy->getAs<EnumType>())
+          break;
+        if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() &&
+            OrigTySize >= Ctx.getTypeSize(Ctx.IntTy))
+          break;
+      }
+
+      needsCast = true;
+      break;
+    }
+
+    case CK_PointerToBoolean:
+    case CK_IntegralToBoolean:
+    case CK_IntegralToFloating:
+    case CK_FloatingToIntegral:
+    case CK_FloatingToBoolean:
+    case CK_FloatingCast:
+    case CK_FloatingComplexToReal:
+    case CK_FloatingComplexToBoolean:
+    case CK_IntegralComplexToReal:
+    case CK_IntegralComplexToBoolean:
+    case CK_AtomicToNonAtomic:
+      needsCast = true;
+      break;
+
+    case CK_Dependent:
+    case CK_BitCast:
+    case CK_LValueBitCast:
+    case CK_BaseToDerived:
+    case CK_DerivedToBase:
+    case CK_UncheckedDerivedToBase:
+    case CK_Dynamic:
+    case CK_ToUnion:
+    case CK_ArrayToPointerDecay:
+    case CK_FunctionToPointerDecay:
+    case CK_NullToPointer:
+    case CK_NullToMemberPointer:
+    case CK_BaseToDerivedMemberPointer:
+    case CK_DerivedToBaseMemberPointer:
+    case CK_MemberPointerToBoolean:
+    case CK_ReinterpretMemberPointer:
+    case CK_ConstructorConversion:
+    case CK_IntegralToPointer:
+    case CK_PointerToIntegral:
+    case CK_ToVoid:
+    case CK_VectorSplat:
+    case CK_CPointerToObjCPointerCast:
+    case CK_BlockPointerToObjCPointerCast:
+    case CK_AnyPointerToBlockPointerCast:
+    case CK_ObjCObjectLValueCast:
+    case CK_FloatingRealToComplex:
+    case CK_FloatingComplexCast:
+    case CK_FloatingComplexToIntegralComplex:
+    case CK_IntegralRealToComplex:
+    case CK_IntegralComplexCast:
+    case CK_IntegralComplexToFloatingComplex:
+    case CK_ARCProduceObject:
+    case CK_ARCConsumeObject:
+    case CK_ARCReclaimReturnedObject:
+    case CK_ARCExtendBlockObject:
+    case CK_NonAtomicToAtomic:
+    case CK_CopyAndAutoreleaseBlockObject:
+      return false;
+    }
+  }
+
+  if (needsCast)
+    return false;
+
+  SourceRange ArgRange = OrigArg->getSourceRange();
+  commit.replaceWithInner(Msg->getSourceRange(), OrigArg->getSourceRange());
+
+  if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg))
+    commit.insertBefore(ArgRange.getBegin(), "@");
+  else
+    commit.insertWrap("@(", ArgRange, ")");
+
+  return true;
+}

Added: cfe/trunk/test/ARCMT/objcmt-boxing.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m?rev=156844&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-boxing.m (added)
+++ cfe/trunk/test/ARCMT/objcmt-boxing.m Tue May 15 14:17:49 2012
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ 
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result
+
+#define YES __objc_yes
+#define NO __objc_no
+
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+typedef signed char BOOL;
+#define nil ((void*) 0)
+
+#define INT_MIN   (-__INT_MAX__  -1)
+
+ at interface NSObject
++ (id)alloc;
+ at end
+
+ at interface NSNumber : NSObject
+ at end
+
+ at interface NSNumber (NSNumberCreation)
+- (id)initWithChar:(char)value;
+- (id)initWithUnsignedChar:(unsigned char)value;
+- (id)initWithShort:(short)value;
+- (id)initWithUnsignedShort:(unsigned short)value;
+- (id)initWithInt:(int)value;
+- (id)initWithUnsignedInt:(unsigned int)value;
+- (id)initWithLong:(long)value;
+- (id)initWithUnsignedLong:(unsigned long)value;
+- (id)initWithLongLong:(long long)value;
+- (id)initWithUnsignedLongLong:(unsigned long long)value;
+- (id)initWithFloat:(float)value;
+- (id)initWithDouble:(double)value;
+- (id)initWithBool:(BOOL)value;
+- (id)initWithInteger:(NSInteger)value;
+- (id)initWithUnsignedInteger:(NSUInteger)value;
+
++ (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;
+ at end
+
+enum MyEnm {
+  ME_foo
+};
+
+void foo() {
+  [NSNumber numberWithInt:INT_MIN];
+  bool cppb;
+  [NSNumber numberWithBool:cppb];
+  MyEnm myenum; 
+  [NSNumber numberWithInteger:myenum];
+  [NSNumber numberWithInteger:ME_foo];
+}

Added: cfe/trunk/test/ARCMT/objcmt-boxing.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-boxing.m.result?rev=156844&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-boxing.m.result (added)
+++ cfe/trunk/test/ARCMT/objcmt-boxing.m.result Tue May 15 14:17:49 2012
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c++ 
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c++ %s.result
+
+#define YES __objc_yes
+#define NO __objc_no
+
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+typedef signed char BOOL;
+#define nil ((void*) 0)
+
+#define INT_MIN   (-__INT_MAX__  -1)
+
+ at interface NSObject
++ (id)alloc;
+ at end
+
+ at interface NSNumber : NSObject
+ at end
+
+ at interface NSNumber (NSNumberCreation)
+- (id)initWithChar:(char)value;
+- (id)initWithUnsignedChar:(unsigned char)value;
+- (id)initWithShort:(short)value;
+- (id)initWithUnsignedShort:(unsigned short)value;
+- (id)initWithInt:(int)value;
+- (id)initWithUnsignedInt:(unsigned int)value;
+- (id)initWithLong:(long)value;
+- (id)initWithUnsignedLong:(unsigned long)value;
+- (id)initWithLongLong:(long long)value;
+- (id)initWithUnsignedLongLong:(unsigned long long)value;
+- (id)initWithFloat:(float)value;
+- (id)initWithDouble:(double)value;
+- (id)initWithBool:(BOOL)value;
+- (id)initWithInteger:(NSInteger)value;
+- (id)initWithUnsignedInteger:(NSUInteger)value;
+
++ (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;
+ at end
+
+enum MyEnm {
+  ME_foo
+};
+
+void foo() {
+  @INT_MIN;
+  bool cppb;
+  @(cppb);
+  MyEnm myenum; 
+  @(myenum);
+  @(ME_foo);
+}

Modified: cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result?rev=156844&r1=156843&r2=156844&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result (original)
+++ cfe/trunk/test/ARCMT/objcmt-numeric-literals.m.result Tue May 15 14:17:49 2012
@@ -468,7 +468,7 @@
   [NSNumber numberWithInteger:NO];
   [NSNumber numberWithInteger:true];
   [NSNumber numberWithInteger:false];
-  [NSNumber numberWithInteger:VAL_INT];
+  @VAL_INT;
   [NSNumber numberWithInteger:VAL_UINT];
 
   [NSNumber numberWithUnsignedInteger:'a'];
@@ -498,5 +498,5 @@
   [NSNumber numberWithUnsignedInteger:true];
   [NSNumber numberWithUnsignedInteger:false];
   [NSNumber numberWithUnsignedInteger:VAL_INT];
-  [NSNumber numberWithUnsignedInteger:VAL_UINT];
+  @VAL_UINT;
 }





More information about the cfe-commits mailing list