summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Driver/Options.td2
-rw-r--r--clang/include/clang/Frontend/FrontendOptions.h5
-rw-r--r--clang/lib/ARCMigrate/ObjCMT.cpp59
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp2
-rw-r--r--clang/test/ARCMT/objcmt-designated-initializer.m44
-rw-r--r--clang/test/ARCMT/objcmt-designated-initializer.m.result44
6 files changed, 155 insertions, 1 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 2281777de31..db4d13ee496 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -184,6 +184,8 @@ def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpoin
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">;
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 4b321e86d29..818427a4ef6 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -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;
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index 1615925eefc..c14fca2738d 100644
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -75,6 +75,10 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
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::migrateAddMethodAnnotation(
}
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::HandleTranslationUnit(ASTContext &Ctx) {
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);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index dfa9ab2fe1a..3ab5330cac3 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -820,6 +820,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
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;
diff --git a/clang/test/ARCMT/objcmt-designated-initializer.m b/clang/test/ARCMT/objcmt-designated-initializer.m
new file mode 100644
index 00000000000..279d4f35d8e
--- /dev/null
+++ b/clang/test/ARCMT/objcmt-designated-initializer.m
@@ -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))
+
+@class NSString;
+
+@interface B1
+-(id)init;
+@end
+
+@interface S1 : B1
+-(id)initWithFoo:(NSString*)foo;
+@end
+
+@implementation S1
+-(id)initWithFoo:(NSString*)foo
+{
+ self = [super init];
+ if (self) {
+ }
+ return self;
+}
+@end
+
+@interface B2
+-(id)init NS_DESIGNATED_INITIALIZER;
+@end
+
+@interface S2 : B2
+-(id)init;
+@end
+
+@implementation S2
+-(id)init
+{
+ self = [super init];
+ if (self) {
+ }
+ return self;
+}
+@end
diff --git a/clang/test/ARCMT/objcmt-designated-initializer.m.result b/clang/test/ARCMT/objcmt-designated-initializer.m.result
new file mode 100644
index 00000000000..4c59b0cc582
--- /dev/null
+++ b/clang/test/ARCMT/objcmt-designated-initializer.m.result
@@ -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))
+
+@class NSString;
+
+@interface B1
+-(id)init;
+@end
+
+@interface S1 : B1
+-(id)initWithFoo:(NSString*)foo NS_DESIGNATED_INITIALIZER;
+@end
+
+@implementation S1
+-(id)initWithFoo:(NSString*)foo
+{
+ self = [super init];
+ if (self) {
+ }
+ return self;
+}
+@end
+
+@interface B2
+-(id)init NS_DESIGNATED_INITIALIZER;
+@end
+
+@interface S2 : B2
+-(id)init;
+@end
+
+@implementation S2
+-(id)init
+{
+ self = [super init];
+ if (self) {
+ }
+ return self;
+}
+@end
OpenPOWER on IntegriCloud