r186856 - Objective-C migration: Use NS_OPTIONS when enumerators

Fariborz Jahanian fjahanian at apple.com
Mon Jul 22 11:53:46 PDT 2013


Author: fjahanian
Date: Mon Jul 22 13:53:45 2013
New Revision: 186856

URL: http://llvm.org/viewvc/llvm-project?rev=186856&view=rev
Log:
Objective-C migration: Use NS_OPTIONS when enumerators
have shift/bitwise operators or are power of 2.

Modified:
    cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
    cfe/trunk/test/ARCMT/objcmt-ns-macros.m
    cfe/trunk/test/ARCMT/objcmt-ns-macros.m.result

Modified: cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=186856&r1=186855&r2=186856&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ObjCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ObjCMT.cpp Mon Jul 22 13:53:45 2013
@@ -399,10 +399,12 @@ static bool rewriteToNSEnumDecl(const En
   return false;
 }
 
-static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
+static bool rewriteToNSMacroDecl(const EnumDecl *EnumDcl,
                                 const TypedefDecl *TypedefDcl,
-                                const NSAPI &NS, edit::Commit &commit) {
-  std::string ClassString = "NS_ENUM(NSInteger, ";
+                                const NSAPI &NS, edit::Commit &commit,
+                                 bool IsNSIntegerType) {
+  std::string ClassString =
+    IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, ";
   ClassString += TypedefDcl->getIdentifier()->getName();
   ClassString += ')';
   SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
@@ -412,6 +414,29 @@ static bool rewriteToNSEnumDecl(const En
   return true;
 }
 
+static bool UseNSOptionsMacro(ASTContext &Ctx,
+                              const EnumDecl *EnumDcl) {
+  bool PowerOfTwo = true;
+  for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(),
+       EE = EnumDcl->enumerator_end(); EI != EE; ++EI) {
+    EnumConstantDecl *Enumerator = (*EI);
+    const Expr *InitExpr = Enumerator->getInitExpr();
+    if (!InitExpr) {
+      PowerOfTwo = false;
+      continue;
+    }
+    InitExpr = InitExpr->IgnoreImpCasts();
+    if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
+      if (BO->isShiftOp() || BO->isBitwiseOp())
+        return true;
+    
+    uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
+    if (PowerOfTwo && EnumVal && !llvm::isPowerOf2_64(EnumVal))
+      PowerOfTwo = false;
+  }
+  return PowerOfTwo;
+}
+
 void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,   
                                             const ObjCImplementationDecl *ImpDecl) {
   const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
@@ -479,23 +504,29 @@ void ObjCMigrateASTConsumer::migrateNSEn
   QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
   bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt);
   bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt);
+  
   if (!IsNSIntegerType && !IsNSUIntegerType) {
     // Also check for typedef enum {...} TD;
     if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
       if (EnumTy->getDecl() == EnumDcl) {
-        // NS_ENUM must be available.
-        if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
+        bool NSOptions = UseNSOptionsMacro(Ctx, EnumDcl);
+        if (NSOptions) {
+          if (!Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
+            return;
+        }
+        else if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
           return;
         edit::Commit commit(*Editor);
-        rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit);
+        rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
         Editor->commit(commit);
-        return;
       }
-      else
-        return;
     }
-    else
-      return;
+    return;
+  }
+  if (IsNSIntegerType && UseNSOptionsMacro(Ctx, EnumDcl)) {
+    // We may still use NS_OPTIONS based on what we find in the enumertor list.
+    IsNSIntegerType = false;
+    IsNSUIntegerType = true;
   }
   
   // NS_ENUM must be available.

Modified: cfe/trunk/test/ARCMT/objcmt-ns-macros.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-ns-macros.m?rev=186856&r1=186855&r2=186856&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-ns-macros.m (original)
+++ cfe/trunk/test/ARCMT/objcmt-ns-macros.m Mon Jul 22 13:53:45 2013
@@ -17,14 +17,13 @@ typedef NSInteger wibble;
 
 enum {
     UIViewAutoresizingNone                 = 0,
-    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
-    UIViewAutoresizingFlexibleWidth        = 1 << 1,
-    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
-    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
-    UIViewAutoresizingFlexibleHeight       = 1 << 4,
-    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
+    UIViewAutoresizingFlexibleLeftMargin,
+    UIViewAutoresizingFlexibleWidth,
+    UIViewAutoresizingFlexibleRightMargin,
+    UIViewAutoresizingFlexibleTopMargin,
+    UIViewAutoresizingFlexibleHeight,
+    UIViewAutoresizingFlexibleBottomMargin
 };
-
 typedef NSUInteger UITableViewCellStyle;
 
 typedef enum {
@@ -35,6 +34,31 @@ typedef enum {
     UIViewAnimationTransitionCurlDown,
 } UIViewAnimationTransition;
 
+typedef enum {
+    UIViewOne   = 0,
+    UIViewTwo   = 1 << 0,
+    UIViewThree = 1 << 1,
+    UIViewFour  = 1 << 2,
+    UIViewFive  = 1 << 3,
+    UIViewSix   = 1 << 4,
+    UIViewSeven = 1 << 5
+} UITableView;
+
+enum {
+  UIOne = 0,
+  UITwo = 0x1,
+  UIthree = 0x8,
+  UIFour = 0x100
+};
+typedef NSInteger UI;
+
+typedef enum {
+  UIP2One = 0,
+  UIP2Two = 0x1,
+  UIP2three = 0x8,
+  UIP2Four = 0x100
+} UIPOWER2;
+
 enum {
   UNOne,
   UNTwo

Modified: cfe/trunk/test/ARCMT/objcmt-ns-macros.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-ns-macros.m.result?rev=186856&r1=186855&r2=186856&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-ns-macros.m.result (original)
+++ cfe/trunk/test/ARCMT/objcmt-ns-macros.m.result Mon Jul 22 13:53:45 2013
@@ -17,16 +17,15 @@ typedef NS_ENUM(NSInteger, wibble) {
 
 typedef NS_OPTIONS(NSUInteger, UITableViewCellStyle) {
     UIViewAutoresizingNone                 = 0,
-    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
-    UIViewAutoresizingFlexibleWidth        = 1 << 1,
-    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
-    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
-    UIViewAutoresizingFlexibleHeight       = 1 << 4,
-    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
+    UIViewAutoresizingFlexibleLeftMargin,
+    UIViewAutoresizingFlexibleWidth,
+    UIViewAutoresizingFlexibleRightMargin,
+    UIViewAutoresizingFlexibleTopMargin,
+    UIViewAutoresizingFlexibleHeight,
+    UIViewAutoresizingFlexibleBottomMargin
 };
 
 
-
 typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
     UIViewAnimationTransitionNone,
     UIViewAnimationTransitionFlipFromLeft,
@@ -35,6 +34,31 @@ typedef NS_ENUM(NSInteger, UIViewAnimati
     UIViewAnimationTransitionCurlDown,
 } ;
 
+typedef NS_OPTIONS(NSUInteger, UITableView) {
+    UIViewOne   = 0,
+    UIViewTwo   = 1 << 0,
+    UIViewThree = 1 << 1,
+    UIViewFour  = 1 << 2,
+    UIViewFive  = 1 << 3,
+    UIViewSix   = 1 << 4,
+    UIViewSeven = 1 << 5
+} ;
+
+typedef NS_OPTIONS(NSUInteger, UI) {
+  UIOne = 0,
+  UITwo = 0x1,
+  UIthree = 0x8,
+  UIFour = 0x100
+};
+
+
+typedef NS_OPTIONS(NSUInteger, UIPOWER2) {
+  UIP2One = 0,
+  UIP2Two = 0x1,
+  UIP2three = 0x8,
+  UIP2Four = 0x100
+} ;
+
 enum {
   UNOne,
   UNTwo





More information about the cfe-commits mailing list