From e3069e231eeeafeaef6078bc585c82dc6a1830e2 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 22 Jul 2013 18:53:45 +0000 Subject: [PATCH] Objective-C migration: Use NS_OPTIONS when enumerators have shift/bitwise operators or are power of 2. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186856 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ARCMigrate/ObjCMT.cpp | 53 ++++++++++++++++++++++------ test/ARCMT/objcmt-ns-macros.m | 38 ++++++++++++++++---- test/ARCMT/objcmt-ns-macros.m.result | 38 ++++++++++++++++---- 3 files changed, 104 insertions(+), 25 deletions(-) diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp index e4ec0c83c5..1bc0b8c891 100644 --- a/lib/ARCMigrate/ObjCMT.cpp +++ b/lib/ARCMigrate/ObjCMT.cpp @@ -399,10 +399,12 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, 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 EnumDecl *EnumDcl, 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(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::migrateNSEnumDecl(ASTContext &Ctx, 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()) { 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. diff --git a/test/ARCMT/objcmt-ns-macros.m b/test/ARCMT/objcmt-ns-macros.m index 42d7d2cd8f..2ca85699fb 100644 --- a/test/ARCMT/objcmt-ns-macros.m +++ b/test/ARCMT/objcmt-ns-macros.m @@ -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 diff --git a/test/ARCMT/objcmt-ns-macros.m.result b/test/ARCMT/objcmt-ns-macros.m.result index ee9b60596f..efd4fe8cec 100644 --- a/test/ARCMT/objcmt-ns-macros.m.result +++ b/test/ARCMT/objcmt-ns-macros.m.result @@ -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, UIViewAnimationTransition) { 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 -- 2.40.0