diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 7a74a98304..93328ca3eb 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -268,6 +268,7 @@ def ObjCRootClass : DiagGroup<"objc-root-class">; def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">; def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>; def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; +def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 869be0477b..ca4e4b9b0d 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6879,7 +6879,11 @@ def warn_ivar_use_hidden : Warning< InGroup>; def warn_direct_initialize_call : Warning< "explicit call to +initialize results in duplicate call to +initialize">, - InGroup>; + InGroup; +def warn_direct_super_initialize_call : Warning< + "explicit call to [super initialize] should only be in implementation " + "of +initialize">, + InGroup; def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; def error_implicit_ivar_access : Error< diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 7ade45d492..a30eaeae36 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -2237,14 +2237,25 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); // Warn about explicit call of +initialize on its own class. But not on 'super'. - if (Method && Method->getMethodFamily() == OMF_initialize && - !SuperLoc.isValid()) { - const ObjCInterfaceDecl *ID = - dyn_cast(Method->getDeclContext()); - if (ID == Class) { - Diag(Loc, diag::warn_direct_initialize_call); - Diag(Method->getLocation(), diag::note_method_declared_at) - << Method->getDeclName(); + if (Method && Method->getMethodFamily() == OMF_initialize) { + if (!SuperLoc.isValid()) { + const ObjCInterfaceDecl *ID = + dyn_cast(Method->getDeclContext()); + if (ID == Class) { + Diag(Loc, diag::warn_direct_initialize_call); + Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + } + } + else if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + // [super initialize] is allowed only within an +initialize implementation + if (CurMeth->getMethodFamily() != OMF_initialize) { + Diag(Loc, diag::warn_direct_super_initialize_call); + Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + Diag(CurMeth->getLocation(), diag::note_method_declared_at) + << CurMeth->getDeclName(); + } } } diff --git a/test/SemaObjC/warn-explicit-call-initialize.m b/test/SemaObjC/warn-explicit-call-initialize.m index 1c7baef15e..99fdf530af 100644 --- a/test/SemaObjC/warn-explicit-call-initialize.m +++ b/test/SemaObjC/warn-explicit-call-initialize.m @@ -2,11 +2,12 @@ // rdar://16628028 @interface NSObject -+ (void)initialize; // expected-note {{method 'initialize' declared here}} ++ (void)initialize; // expected-note 2 {{method 'initialize' declared here}} @end @interface I : NSObject + (void)initialize; // expected-note {{method 'initialize' declared here}} ++ (void)SomeRandomMethod; @end @implementation I @@ -17,5 +18,8 @@ + (void)initialize { [super initialize]; } ++ (void)SomeRandomMethod { // expected-note {{method 'SomeRandomMethod' declared here}} + [super initialize]; // expected-warning {{explicit call to [super initialize] should only be in implementation of +initialize}} +} @end