r196943 - [objcmt] Add a modernization option to infer and suggest designated initializers.

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Dec 10 10:36:49 PST 2013


Author: akirtzidis
Date: Tue Dec 10 12:36:49 2013
New Revision: 196943

URL: http://llvm.org/viewvc/llvm-project?rev=196943&view=rev
Log:
[objcmt] Add a modernization option to infer and suggest designated initializers.

rdar://15509284

Added:
    cfe/trunk/test/ARCMT/objcmt-designated-initializer.m
    cfe/trunk/test/ARCMT/objcmt-designated-initializer.m.result
Modified:
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Frontend/FrontendOptions.h
    cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=196943&r1=196942&r2=196943&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Tue Dec 10 12:36:49 2013
@@ -184,6 +184,8 @@ def objcmt_returns_innerpointer_property
   HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
 def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
   HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
+def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
+  HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
 def objcmt_white_list_dir_path: Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
   HelpText<"Only modify files with a filename contained in the provided directory path">;
 

Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=196943&r1=196942&r2=196943&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Tue Dec 10 12:36:49 2013
@@ -179,10 +179,13 @@ public:
     ObjCMT_ReturnsInnerPointerProperty = 0x200,
     /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
     ObjCMT_NsAtomicIOSOnlyProperty = 0x400,
+    /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
+    ObjCMT_DesignatedInitializer = 0x800,
     ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
                            ObjCMT_Annotation | ObjCMT_Instancetype |
                            ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
-                           ObjCMT_NsAtomicIOSOnlyProperty),
+                           ObjCMT_NsAtomicIOSOnlyProperty |
+                           ObjCMT_DesignatedInitializer),
     ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls)
   };
   unsigned ObjCMTAction;

Modified: cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=196943&r1=196942&r2=196943&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ObjCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ObjCMT.cpp Tue Dec 10 12:36:49 2013
@@ -75,6 +75,10 @@ class ObjCMigrateASTConsumer : public AS
   
   void migrateAddMethodAnnotation(ASTContext &Ctx,
                                   const ObjCMethodDecl *MethodDecl);
+
+  void inferDesignatedInitializers(ASTContext &Ctx,
+                                   const ObjCImplementationDecl *ImplD);
+
 public:
   std::string MigrateDir;
   unsigned ASTMigrateActions;
@@ -1539,6 +1543,55 @@ void ObjCMigrateASTConsumer::migrateAddM
 }
 
 namespace {
+class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
+public:
+  bool shouldVisitTemplateInstantiations() const { return false; }
+  bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+    if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
+      if (E->getMethodFamily() == OMF_init)
+        return false;
+    }
+    return true;
+  }
+};
+} // anonymous namespace
+
+static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
+  return !SuperInitChecker().TraverseStmt(MD->getBody());
+}
+
+void ObjCMigrateASTConsumer::inferDesignatedInitializers(
+    ASTContext &Ctx,
+    const ObjCImplementationDecl *ImplD) {
+
+  const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
+  if (!IFace || IFace->hasDesignatedInitializers())
+    return;
+  if (!Ctx.Idents.get("NS_DESIGNATED_INITIALIZER").hasMacroDefinition())
+    return;
+
+  for (ObjCImplementationDecl::instmeth_iterator
+         I = ImplD->instmeth_begin(), E = ImplD->instmeth_end(); I != E; ++I) {
+    const ObjCMethodDecl *MD = *I;
+    if (MD->isDeprecated() ||
+        MD->getMethodFamily() != OMF_init ||
+        MD->isDesignatedInitializerForTheInterface())
+      continue;
+    const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
+                                                    /*isInstance=*/true);
+    if (!IFaceM)
+      continue;
+    if (hasSuperInitCall(MD)) {
+      edit::Commit commit(*Editor);
+      commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER");
+      Editor->commit(commit);
+    }
+  }
+}
+
+namespace {
 
 class RewritesReceiver : public edit::EditsReceiver {
   Rewriter &Rewrite;
@@ -1657,6 +1710,12 @@ void ObjCMigrateASTConsumer::HandleTrans
         if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
           migrateARCSafeAnnotation(Ctx, CDecl);
       }
+
+      if (const ObjCImplementationDecl *
+            ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
+        if (ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer)
+          inferDesignatedInitializers(Ctx, ImplD);
+      }
     }
     if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
       AnnotateImplicitBridging(Ctx);

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=196943&r1=196942&r2=196943&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue Dec 10 12:36:49 2013
@@ -820,6 +820,8 @@ static InputKind ParseFrontendArgs(Front
     Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty;
   if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly))
     Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty;
+  if (Args.hasArg(OPT_objcmt_migrate_designated_init))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_DesignatedInitializer;
   if (Args.hasArg(OPT_objcmt_migrate_all))
     Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls;
 

Added: cfe/trunk/test/ARCMT/objcmt-designated-initializer.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-designated-initializer.m?rev=196943&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-designated-initializer.m (added)
+++ cfe/trunk/test/ARCMT/objcmt-designated-initializer.m Tue Dec 10 12:36:49 2013
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-designated-init %s -triple x86_64-apple-darwin11 -fobjc-arc -migrate -o %t.remap
+// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -x objective-c -fobjc-arc %s.result
+
+#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
+
+ at class NSString;
+
+ at interface B1
+-(id)init;
+ at end
+
+ at interface S1 : B1
+-(id)initWithFoo:(NSString*)foo;
+ at end
+
+ at implementation S1
+-(id)initWithFoo:(NSString*)foo
+{
+  self = [super init];
+  if (self) {
+  }
+  return self;
+}
+ at end
+
+ at interface B2
+-(id)init NS_DESIGNATED_INITIALIZER;
+ at end
+
+ at interface S2 : B2
+-(id)init;
+ at end
+
+ at implementation S2
+-(id)init
+{
+  self = [super init];
+  if (self) {
+  }
+  return self;
+}
+ at end

Added: cfe/trunk/test/ARCMT/objcmt-designated-initializer.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-designated-initializer.m.result?rev=196943&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-designated-initializer.m.result (added)
+++ cfe/trunk/test/ARCMT/objcmt-designated-initializer.m.result Tue Dec 10 12:36:49 2013
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -objcmt-migrate-designated-init %s -triple x86_64-apple-darwin11 -fobjc-arc -migrate -o %t.remap
+// RUN: c-arcmt-test %t.remap | arcmt-test -verify-transformed-files %s.result
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -x objective-c -fobjc-arc %s.result
+
+#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
+
+ at class NSString;
+
+ at interface B1
+-(id)init;
+ at end
+
+ at interface S1 : B1
+-(id)initWithFoo:(NSString*)foo NS_DESIGNATED_INITIALIZER;
+ at end
+
+ at implementation S1
+-(id)initWithFoo:(NSString*)foo
+{
+  self = [super init];
+  if (self) {
+  }
+  return self;
+}
+ at end
+
+ at interface B2
+-(id)init NS_DESIGNATED_INITIALIZER;
+ at end
+
+ at interface S2 : B2
+-(id)init;
+ at end
+
+ at implementation S2
+-(id)init
+{
+  self = [super init];
+  if (self) {
+  }
+  return self;
+}
+ at end





More information about the cfe-commits mailing list