]> granicus.if.org Git - clang/commitdiff
Objective-C. Warn if user has made explicit call
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 22 Aug 2014 16:57:26 +0000 (16:57 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 22 Aug 2014 16:57:26 +0000 (16:57 +0000)
to +initilize as this results in an extra call
to this method. rdar://16628028

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216271 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/IdentifierTable.h
lib/AST/DeclObjC.cpp
lib/Basic/IdentifierTable.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
test/SemaObjC/warn-explicit-call-initialize.m [new file with mode: 0644]

index 4cdc6c084b90c050b3c9c4b5a54c62c112087dc9..a55538eed1ec06722fe844130b19d80f7833e14e 100644 (file)
@@ -6874,6 +6874,9 @@ def err_invalid_protocol_qualifiers : Error<
 def warn_ivar_use_hidden : Warning<
   "local declaration of %0 hides instance variable">,
    InGroup<DiagGroup<"shadow-ivar">>;
+def warn_direct_initialize_call : Warning<
+  "explicit call to +initialize results in duplicate call to +initialize">,
+   InGroup<DiagGroup<"explicit-initialize-call">>;
 def error_ivar_use_in_class_method : Error<
   "instance variable %0 accessed in class method">;
 def error_implicit_ivar_access : Error<
index 0c278a17a32deb5e11e9497817cba8b7dddb6a22..e63e04f77250be520bd338d9c87e2bb2daf5d30b 100644 (file)
@@ -563,6 +563,7 @@ enum ObjCMethodFamily {
   OMF_retain,
   OMF_retainCount,
   OMF_self,
+  OMF_initialize,
 
   // performSelector families
   OMF_performSelector
index 4657cf371b2f0298d68d57fc54ee138f2e298ae7..e753feb3d9e4dc7d15934a6591672b704c1f2e85 100644 (file)
@@ -849,6 +849,11 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
       family = OMF_None;
     break;
       
+  case OMF_initialize:
+    if (isInstanceMethod() || !getReturnType()->isVoidType())
+      family = OMF_None;
+    break;
+      
   case OMF_performSelector:
     if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
       family = OMF_None;
index 219845996323c652787ac9d3735e87cc225a7603..01f60a9d695af8199a8acf854ac6bbfe35620cbe 100644 (file)
@@ -428,6 +428,7 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
     if (name == "retain") return OMF_retain;
     if (name == "retainCount") return OMF_retainCount;
     if (name == "self") return OMF_self;
+    if (name == "initialize") return OMF_initialize;
   }
  
   if (name == "performSelector") return OMF_performSelector;
index 8e3e85ed281b32f6631a55e8092f88c3ed098b5c..90a6264cb120cb1495df682b9e64073f68005481 100644 (file)
@@ -201,6 +201,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
   case OMF_autorelease:
   case OMF_retainCount:
   case OMF_self:
+  case OMF_initialize:
   case OMF_performSelector:
     return false;
 
@@ -353,6 +354,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
     case OMF_copy:
     case OMF_new:
     case OMF_self:
+    case OMF_initialize:
     case OMF_performSelector:
       break;
     }
@@ -1515,6 +1517,7 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
   case OMF_finalize:
   case OMF_retainCount:
   case OMF_self:
+  case OMF_initialize:
   case OMF_performSelector:
     // Mismatches for these methods don't change ownership
     // conventions, so we don't care.
@@ -3259,6 +3262,7 @@ Decl *Sema::ActOnMethodDeclaration(
     case OMF_mutableCopy:
     case OMF_release:
     case OMF_retainCount:
+    case OMF_initialize:
     case OMF_performSelector:
       break;
       
index 582e1834d480335df2e81375ba3f19873822b1f5..cbf41b5069a71744731567e50847a8444a6f021f 100644 (file)
@@ -1137,6 +1137,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
     case OMF_mutableCopy:
     case OMF_new:
     case OMF_self:
+    case OMF_initialize:
     case OMF_performSelector:
       break;
     }
@@ -2230,6 +2231,17 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
       RequireCompleteType(LBracLoc, Method->getReturnType(),
                           diag::err_illegal_message_expr_incomplete_type))
     return ExprError();
+  
+  // Warn about explicit call of +initialize on its own class.
+  if (Method && Method->getMethodFamily() == OMF_initialize) {
+    const ObjCInterfaceDecl *ID =
+      dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext());
+    if (ID == Class) {
+      Diag(Loc, diag::warn_direct_initialize_call);
+      Diag(Method->getLocation(), diag::note_method_declared_at)
+      << Method->getDeclName();
+    }
+  }
 
   // Construct the appropriate ObjCMessageExpr.
   ObjCMessageExpr *Result;
@@ -2652,6 +2664,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
     case OMF_mutableCopy:
     case OMF_new:
     case OMF_self:
+    case OMF_initialize:
       break;
 
     case OMF_dealloc:
index eb699d694087239ff587e56682d950be9618c298..6e49fbb5d604e1178e74250fc1b8885076ec36d0 100644 (file)
@@ -1359,6 +1359,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
   // Check the method family, and apply any default annotations.
   switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
     case OMF_None:
+    case OMF_initialize:
     case OMF_performSelector:
       // Assume all Objective-C methods follow Cocoa Memory Management rules.
       // FIXME: Does the non-threaded performSelector family really belong here?
diff --git a/test/SemaObjC/warn-explicit-call-initialize.m b/test/SemaObjC/warn-explicit-call-initialize.m
new file mode 100644 (file)
index 0000000..786894c
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1  -fsyntax-only  -triple x86_64-apple-darwin10 -verify %s
+// rdar://16628028
+
+@interface NSObject
++ (void)initialize; // expected-note {{method 'initialize' declared here}}
+@end
+
+@interface I : NSObject 
++ (void)initialize; // expected-note {{method 'initialize' declared here}}
+@end
+
+@implementation I
+- (void) Meth { 
+  [I initialize];     // expected-warning {{explicit call to +initialize results in duplicate call to +initialize}} 
+  [NSObject initialize]; // expected-warning {{explicit call to +initialize results in duplicate call to +initialize}}
+}
++ (void)initialize {}
+@end
+