ObjectiveC migration. Check-in patch reverted in r187634.
Also removed check for "NS" prefix for class name.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187655 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 8e12b97..0bc13e6 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -586,10 +586,7 @@
   OIT_None,
   OIT_Array,
   OIT_Dictionary,
-  OIT_MemManage,
-  OIT_NSString,
-  OIT_NSSet,
-  OIT_NSURL
+  OIT_MemManage
 };
 
 /// \brief Smart pointer class that efficiently represents Objective-C method
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 2b2f922..f7a36e2 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -41,6 +41,8 @@
   void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
   void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
                                  ObjCMethodDecl *OM);
+  void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
+                            ObjCMethodDecl *OM);
 
 public:
   std::string MigrateDir;
@@ -549,13 +551,34 @@
   Editor->commit(commit);
 }
 
+static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC,
+                                    ObjCMethodDecl *OM) {
+  SourceRange R;
+  std::string ClassString;
+  if (TypeSourceInfo *TSInfo =  OM->getResultTypeSourceInfo()) {
+    TypeLoc TL = TSInfo->getTypeLoc();
+    R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
+    ClassString = "instancetype";
+  }
+  else {
+    R = SourceRange(OM->getLocStart(), OM->getLocStart());
+    ClassString = OM->isInstanceMethod() ? '-' : '+';
+    ClassString += " (instancetype)";
+  }
+  edit::Commit commit(*ASTC.Editor);
+  commit.replace(R, ClassString);
+  ASTC.Editor->commit(commit);
+}
+
 void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
                                                        ObjCContainerDecl *CDecl,
                                                        ObjCMethodDecl *OM) {
   ObjCInstanceTypeFamily OIT_Family =
     Selector::getInstTypeMethodFamily(OM->getSelector());
-  if (OIT_Family == OIT_None)
+  if (OIT_Family == OIT_None) {
+    migrateFactoryMethod(Ctx, CDecl, OM);
     return;
+  }
   std::string ClassName;
   switch (OIT_Family) {
     case OIT_Array:
@@ -581,24 +604,11 @@
       IDecl = ImpDecl->getClassInterface();
   }
   if (!IDecl ||
-      !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName)))
+      !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
+    migrateFactoryMethod(Ctx, CDecl, OM);
     return;
-  
-  SourceRange R;
-  std::string ClassString;
-  if (TypeSourceInfo *TSInfo =  OM->getResultTypeSourceInfo()) {
-    TypeLoc TL = TSInfo->getTypeLoc();
-    R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
-    ClassString = "instancetype";
   }
-  else {
-    R = SourceRange(OM->getLocStart(), OM->getLocStart());
-    ClassString = OM->isInstanceMethod() ? '-' : '+';
-    ClassString += " (instancetype)";
-  }
-  edit::Commit commit(*Editor);
-  commit.replace(R, ClassString);
-  Editor->commit(commit);
+  ReplaceWithInstancetype(*this, OM);
 }
 
 void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx,
@@ -612,6 +622,43 @@
   }
 }
 
+void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
+                                                  ObjCContainerDecl *CDecl,
+                                                  ObjCMethodDecl *OM) {
+  if (OM->isInstanceMethod() || !OM->getResultType()->isObjCIdType())
+    return;
+  
+  // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
+  // NSYYYNamE with matching names be at least 3 characters long.
+  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
+  if (!IDecl) {
+    if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
+      IDecl = CatDecl->getClassInterface();
+    else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
+      IDecl = ImpDecl->getClassInterface();
+  }
+  if (!IDecl)
+    return;
+  
+  std::string StringClassName = IDecl->getName();
+  StringRef LoweredClassName(StringClassName);
+  LoweredClassName = LoweredClassName.lower();
+  IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
+  std::string MethodName = MethodIdName->getName();
+  std::string MethodNameSubStr = MethodName.substr(0, 3);
+  StringRef MethodNamePrefix(MethodNameSubStr);
+  MethodNamePrefix = MethodNamePrefix.lower();
+  size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
+  if (Ix == StringRef::npos)
+    return;
+  std::string ClassNamePostfix = LoweredClassName.substr(Ix);
+  StringRef LoweredMethodName(MethodName);
+  LoweredMethodName = LoweredMethodName.lower();
+  if (!LoweredMethodName.startswith(ClassNamePostfix))
+    return;
+  ReplaceWithInstancetype(*this, OM);
+}
+
 namespace {
 
 class RewritesReceiver : public edit::EditsReceiver {
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 96d9e56..3572930 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -474,14 +474,6 @@
     case 'r':
       if (startsWithWord(name, "retain")) return OIT_MemManage;
       break;
-    case 's':
-      if (startsWithWord(name, "string")) return OIT_NSString;
-      else
-        if (startsWithWord(name, "set")) return OIT_NSSet;
-      break;
-    case 'U':
-      if (startsWithWord(name, "URL")) return OIT_NSURL;
-      break;
     default:
       break;
   }
diff --git a/test/ARCMT/objcmt-instancetype-2.m b/test/ARCMT/objcmt-instancetype-2.m
new file mode 100644
index 0000000..aff9998
--- /dev/null
+++ b/test/ARCMT/objcmt-instancetype-2.m
@@ -0,0 +1,76 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
+
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+typedef char BOOL;
+@class NSData, NSError, NSProtocolChecker, NSObject;
+@class NSPortNameServer, NSTimeZone;
+
+@interface NSMutableString
+@end
+
+@interface NSString @end
+
+@class NSString, NSURL;
+@interface NSString (NSStringDeprecated)
++ (id)stringWithContentsOfFile:(NSString *)path __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (id)stringWithContentsOfURL:(NSURL *)url __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (id)stringWithCString:(const char *)bytes length:(NSUInteger)length __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (id)stringWithCString:(const char *)bytes __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
+@end
+
+
+typedef enum NSURLBookmarkResolutionOptions {
+                Bookmark
+} NSURLBookmarkResolutionOptions;
+
+@interface NSURL
++ (id)URLWithString:(NSString *)URLString;
++ (id)URLWithString:(NSString *)URLString relativeToURL:(NSURL *)baseURL;
++ (id)URLByResolvingBookmarkData:(NSData *)bookmarkData options:(NSURLBookmarkResolutionOptions)options relativeToURL:(NSURL *)relativeURL bookmarkDataIsStale:(BOOL *)isStale error:(NSError **)error __attribute__((availability(macosx,introduced=10.6)));
+@end
+
+@class NSDictionary;
+@interface NSError
++ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict;
+@end
+
+
+@interface NSMutableString (NSMutableStringExtensionMethods)
++ (id)stringWithCapacity:(NSUInteger)capacity;
+@end
+
+@interface NSMutableData
++ (id)dataWithCapacity:(NSUInteger)aNumItems;
++ (id)dataWithLength:(NSUInteger)length;
+@end
+
+@interface NSMutableDictionary @end
+
+@interface NSMutableDictionary (NSSharedKeySetDictionary)
++ (id )dictionaryWithSharedKeySet:(id)keyset __attribute__((availability(macosx,introduced=10.8)));
+@end
+
+@interface NSProtocolChecker
++ (id)protocolCheckerWithTarget:(NSObject *)anObject protocol:(Protocol *)aProtocol;
+@end
+
+@interface NSConnection
++ (id)connectionWithRegisteredName:(NSString *)name host:(NSString *)hostName;
++ (id)connectionWithRegisteredName:(NSString *)name host:(NSString *)hostName usingNameServer:(NSPortNameServer *)server;
+@end
+
+@interface NSDate
++ (id)dateWithString:(NSString *)aString __attribute__((availability(macosx,introduced=10.4)));
+@end
+
+@interface NSCalendarDate : NSDate
++ (id)calendarDate __attribute__((availability(macosx,introduced=10.4)));
++ (id)dateWithString:(NSString *)description calendarFormat:(NSString *)format locale:(id)locale __attribute__((availability(macosx,introduced=10.4)));
++ (id)dateWithString:(NSString *)description calendarFormat:(NSString *)format __attribute__((availability(macosx,introduced=10.4)));
++ (id)dateWithYear:(NSInteger)year month:(NSUInteger)month day:(NSUInteger)day hour:(NSUInteger)hour minute:(NSUInteger)minute second:(NSUInteger)second timeZone:(NSTimeZone *)aTimeZone __attribute__((availability(macosx,introduced=10.4)));
+@end
+
diff --git a/test/ARCMT/objcmt-instancetype-2.m.result b/test/ARCMT/objcmt-instancetype-2.m.result
new file mode 100644
index 0000000..ba66480
--- /dev/null
+++ b/test/ARCMT/objcmt-instancetype-2.m.result
@@ -0,0 +1,76 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11
+// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
+
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+typedef char BOOL;
+@class NSData, NSError, NSProtocolChecker, NSObject;
+@class NSPortNameServer, NSTimeZone;
+
+@interface NSMutableString
+@end
+
+@interface NSString @end
+
+@class NSString, NSURL;
+@interface NSString (NSStringDeprecated)
++ (instancetype)stringWithContentsOfFile:(NSString *)path __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (instancetype)stringWithContentsOfURL:(NSURL *)url __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (instancetype)stringWithCString:(const char *)bytes length:(NSUInteger)length __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
++ (instancetype)stringWithCString:(const char *)bytes __attribute__((availability(macosx,introduced=10.0 ,deprecated=10.4,message="" )));
+@end
+
+
+typedef enum NSURLBookmarkResolutionOptions {
+                Bookmark
+} NSURLBookmarkResolutionOptions;
+
+@interface NSURL
++ (instancetype)URLWithString:(NSString *)URLString;
++ (instancetype)URLWithString:(NSString *)URLString relativeToURL:(NSURL *)baseURL;
++ (instancetype)URLByResolvingBookmarkData:(NSData *)bookmarkData options:(NSURLBookmarkResolutionOptions)options relativeToURL:(NSURL *)relativeURL bookmarkDataIsStale:(BOOL *)isStale error:(NSError **)error __attribute__((availability(macosx,introduced=10.6)));
+@end
+
+@class NSDictionary;
+@interface NSError
++ (instancetype)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict;
+@end
+
+
+@interface NSMutableString (NSMutableStringExtensionMethods)
++ (instancetype)stringWithCapacity:(NSUInteger)capacity;
+@end
+
+@interface NSMutableData
++ (instancetype)dataWithCapacity:(NSUInteger)aNumItems;
++ (instancetype)dataWithLength:(NSUInteger)length;
+@end
+
+@interface NSMutableDictionary @end
+
+@interface NSMutableDictionary (NSSharedKeySetDictionary)
++ (instancetype )dictionaryWithSharedKeySet:(id)keyset __attribute__((availability(macosx,introduced=10.8)));
+@end
+
+@interface NSProtocolChecker
++ (instancetype)protocolCheckerWithTarget:(NSObject *)anObject protocol:(Protocol *)aProtocol;
+@end
+
+@interface NSConnection
++ (instancetype)connectionWithRegisteredName:(NSString *)name host:(NSString *)hostName;
++ (instancetype)connectionWithRegisteredName:(NSString *)name host:(NSString *)hostName usingNameServer:(NSPortNameServer *)server;
+@end
+
+@interface NSDate
++ (instancetype)dateWithString:(NSString *)aString __attribute__((availability(macosx,introduced=10.4)));
+@end
+
+@interface NSCalendarDate : NSDate
++ (instancetype)calendarDate __attribute__((availability(macosx,introduced=10.4)));
++ (instancetype)dateWithString:(NSString *)description calendarFormat:(NSString *)format locale:(id)locale __attribute__((availability(macosx,introduced=10.4)));
++ (instancetype)dateWithString:(NSString *)description calendarFormat:(NSString *)format __attribute__((availability(macosx,introduced=10.4)));
++ (instancetype)dateWithYear:(NSInteger)year month:(NSUInteger)month day:(NSUInteger)day hour:(NSUInteger)hour minute:(NSUInteger)minute second:(NSUInteger)second timeZone:(NSTimeZone *)aTimeZone __attribute__((availability(macosx,introduced=10.4)));
+@end
+
diff --git a/test/ARCMT/objcmt-instancetype.m.result b/test/ARCMT/objcmt-instancetype.m.result
index 7bc554f..ad8fcae 100644
--- a/test/ARCMT/objcmt-instancetype.m.result
+++ b/test/ARCMT/objcmt-instancetype.m.result
@@ -11,7 +11,7 @@
 @end
 
 @interface NSString : NSObject
-+ (id)stringWithString:(NSString *)string;
++ (instancetype)stringWithString:(NSString *)string;
 - (instancetype)initWithString:(NSString *)aString;
 @end