From 35ee87debe55cdf4e41611f33cb43b933840d5b2 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 6 Oct 2014 23:50:37 +0000 Subject: [PATCH] Objective-C SDK modernizer. Patch to support modernization to NS_ENUM/NS_OPTION macros when typedef names are other than NSInteger/NSUInteger (int8_t, etc.). rdar://18532199 llvm-svn: 219173 --- clang/include/clang/AST/NSAPI.h | 5 ++- clang/lib/ARCMigrate/ObjCMT.cpp | 42 +++++++++++++--------- clang/lib/AST/NSAPI.cpp | 27 ++++++++++++++ clang/test/ARCMT/objcmt-ns-macros.m | 41 +++++++++++++++++++++ clang/test/ARCMT/objcmt-ns-macros.m.result | 37 +++++++++++++++++++ 5 files changed, 135 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/AST/NSAPI.h b/clang/include/clang/AST/NSAPI.h index 56739354dcdd..764bf1912f98 100644 --- a/clang/include/clang/AST/NSAPI.h +++ b/clang/include/clang/AST/NSAPI.h @@ -104,7 +104,7 @@ public: NSDict_initWithObjectsForKeysCount }; static const unsigned NumNSDictionaryMethods = 12; - + /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; @@ -187,6 +187,9 @@ public: bool isObjCNSIntegerType(QualType T) const; /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. bool isObjCNSUIntegerType(QualType T) const; + /// \brief Returns one of NSIntegral typedef names if \param T is a typedef + /// of that name in objective-c. + StringRef GetNSIntegralKind(QualType T) const; private: bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index ea1914c085c0..f9c6e6e644fc 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -584,18 +584,32 @@ static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, return true; } +static StringRef GetUnsignedName(StringRef NSIntegerName) { + StringRef UnsignedName = llvm::StringSwitch(NSIntegerName) + .Case("int8_t", "uint8_t") + .Case("int16_t", "uint16_t") + .Case("int32_t", "uint32_t") + .Case("NSInteger", "NSUInteger") + .Case("int64_t", "uint64_t") + .Default(NSIntegerName); + return UnsignedName; +} + static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, - bool IsNSIntegerType, + StringRef NSIntegerName, bool NSOptions) { std::string ClassString; - if (NSOptions) - ClassString = "typedef NS_OPTIONS(NSUInteger, "; - else - ClassString = - IsNSIntegerType ? "typedef NS_ENUM(NSInteger, " - : "typedef NS_ENUM(NSUInteger, "; + if (NSOptions) { + ClassString = "typedef NS_OPTIONS("; + ClassString += GetUnsignedName(NSIntegerName); + } + else { + ClassString = "typedef NS_ENUM("; + ClassString += NSIntegerName; + } + ClassString += ", "; ClassString += TypedefDcl->getIdentifier()->getName(); ClassString += ')'; @@ -788,10 +802,9 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, return false; QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); - bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt); - bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt); + StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt); - if (!IsNSIntegerType && !IsNSUIntegerType) { + if (NSIntegerName.empty()) { // Also check for typedef enum {...} TD; if (const EnumType *EnumTy = qt->getAs()) { if (EnumTy->getDecl() == EnumDcl) { @@ -813,15 +826,12 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, // We may still use NS_OPTIONS based on what we find in the enumertor list. bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl); - // NS_ENUM must be available. - if (IsNSIntegerType && !Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) - return false; - // NS_OPTIONS must be available. - if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition()) + // For sanity check, see if macro NS_ENUM can be seen. + if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) return false; edit::Commit commit(*Editor); bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, - commit, IsNSIntegerType, NSOptions); + commit, NSIntegerName, NSOptions); Editor->commit(commit); return Res; } diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp index 579a92cacc90..aac31e7f15c3 100644 --- a/clang/lib/AST/NSAPI.cpp +++ b/clang/lib/AST/NSAPI.cpp @@ -10,6 +10,7 @@ #include "clang/AST/NSAPI.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -400,6 +401,32 @@ bool NSAPI::isObjCNSUIntegerType(QualType T) const { return isObjCTypedef(T, "NSUInteger", NSUIntegerId); } +StringRef NSAPI::GetNSIntegralKind(QualType T) const { + if (!Ctx.getLangOpts().ObjC1 || T.isNull()) + return StringRef(); + + while (const TypedefType *TDT = T->getAs()) { + StringRef NSIntegralResust = + llvm::StringSwitch( + TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName()) + .Case("int8_t", "int8_t") + .Case("int16_t", "int16_t") + .Case("int32_t", "int32_t") + .Case("NSInteger", "NSInteger") + .Case("int64_t", "int64_t") + .Case("uint8_t", "uint8_t") + .Case("uint16_t", "uint16_t") + .Case("uint32_t", "uint32_t") + .Case("NSUInteger", "NSUInteger") + .Case("uint64_t", "uint64_t") + .Default(StringRef()); + if (!NSIntegralResust.empty()) + return NSIntegralResust; + T = TDT->desugar(); + } + return StringRef(); +} + bool NSAPI::isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const { if (!Ctx.getLangOpts().ObjC1) diff --git a/clang/test/ARCMT/objcmt-ns-macros.m b/clang/test/ARCMT/objcmt-ns-macros.m index 2f60cb9f0cea..1d5583b92f26 100644 --- a/clang/test/ARCMT/objcmt-ns-macros.m +++ b/clang/test/ARCMT/objcmt-ns-macros.m @@ -3,8 +3,17 @@ // 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 -fobjc-runtime-has-weak -fobjc-arc %s.result +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; typedef long NSInteger; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; typedef unsigned long NSUInteger; +typedef unsigned long long uint64_t; #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type @@ -322,3 +331,35 @@ typedef enum { NumericEnum4; +// rdar://18532199 +enum +{ + UI8one = 1 +}; +typedef int8_t MyEnumeratedType; + + +enum { + UI16One = 0, + UI16Two = 0x1, + UI16three = 0x8, + UI16Four = 0x100 +}; +typedef int16_t UI16; + +enum { + UI32ViewAutoresizingNone = 0, + UI32ViewAutoresizingFlexibleLeftMargin, + UI32ViewAutoresizingFlexibleWidth, + UI32ViewAutoresizingFlexibleRightMargin, + UI32ViewAutoresizingFlexibleTopMargin, + UI32ViewAutoresizingFlexibleHeight, + UI32ViewAutoresizingFlexibleBottomMargin +}; +typedef uint32_t UI32TableViewCellStyle; + +enum +{ + UIU8one = 1 +}; +typedef uint8_t UI8Type; diff --git a/clang/test/ARCMT/objcmt-ns-macros.m.result b/clang/test/ARCMT/objcmt-ns-macros.m.result index 07a8a72f7280..42f3239c84b4 100644 --- a/clang/test/ARCMT/objcmt-ns-macros.m.result +++ b/clang/test/ARCMT/objcmt-ns-macros.m.result @@ -3,8 +3,17 @@ // 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 -fobjc-runtime-has-weak -fobjc-arc %s.result +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; typedef long NSInteger; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; typedef unsigned long NSUInteger; +typedef unsigned long long uint64_t; #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type @@ -302,3 +311,31 @@ typedef NS_OPTIONS(NSUInteger, NumericEnum4) { Four = 4 }; +// rdar://18532199 +typedef NS_ENUM(int8_t, MyEnumeratedType) +{ + UI8one = 1 +}; + + +typedef NS_OPTIONS(uint16_t, UI16) { + UI16One = 0, + UI16Two = 0x1, + UI16three = 0x8, + UI16Four = 0x100 +}; + +typedef NS_ENUM(uint32_t, UI32TableViewCellStyle) { + UI32ViewAutoresizingNone = 0, + UI32ViewAutoresizingFlexibleLeftMargin, + UI32ViewAutoresizingFlexibleWidth, + UI32ViewAutoresizingFlexibleRightMargin, + UI32ViewAutoresizingFlexibleTopMargin, + UI32ViewAutoresizingFlexibleHeight, + UI32ViewAutoresizingFlexibleBottomMargin +}; + +typedef NS_ENUM(uint8_t, UI8Type) +{ + UIU8one = 1 +};