]> granicus.if.org Git - clang/commitdiff
Warn on missing [super dealloc] calls.
authorNico Weber <nicolasweber@gmx.de>
Mon, 22 Aug 2011 17:25:57 +0000 (17:25 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 22 Aug 2011 17:25:57 +0000 (17:25 +0000)
This matches gcc's logic. Half of PR10661.

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

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/warn-missing-super.m [new file with mode: 0644]

index e7b061647cc0350d5fe52d97b1c9232bcf67b624..add2ac365c34f6dc57f4c390b791f0e13a68bbde 100644 (file)
@@ -96,6 +96,7 @@ def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
 def : DiagGroup<"overflow">;
 def OverlengthStrings : DiagGroup<"overlength-strings">;
 def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
 def Packed : DiagGroup<"packed">;
 def Padded : DiagGroup<"padded">;
 def PointerArith : DiagGroup<"pointer-arith">;
@@ -273,6 +274,7 @@ def Most : DiagGroup<"most", [
     UnknownPragmas,
     Unused,
     VolatileRegisterVar,
+    ObjCMissingSuperCalls,
     OverloadedVirtual
  ]>;
 
index c76dca0f7baf14591bceaa735fc194206c25f7fa..89ffebbbab9accf7e8aea6eb16c2278fa75c5b4b 100644 (file)
@@ -570,6 +570,9 @@ def error_property_implemented : Error<"property %0 is already implemented">;
 def warn_objc_property_attr_mutually_exclusive : Warning<
   "property attributes '%0' and '%1' are mutually exclusive">,
   InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
+def warn_objc_missing_super_dealloc : Warning<
+  "method possibly missing a [super dealloc] call">,
+  InGroup<ObjCMissingSuperCalls>;
 def warn_undeclared_selector : Warning<
   "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
 def warn_implicit_atomic_property : Warning<
index 4bb014b88aac2c0a402851b4c20cf3cff6348bd7..07bbd18bee8ed2efc9fdd541a9b8886c2315748c 100644 (file)
@@ -489,6 +489,11 @@ public:
   /// have been declared.
   bool GlobalNewDeleteDeclared;
 
+
+  /// A flag that is set when parsing a -dealloc method and no [super dealloc]
+  /// call was found yet.
+  bool ObjCShouldCallSuperDealloc;
+
   /// \brief The set of declarations that have been referenced within
   /// a potentially evaluated expression.
   typedef SmallVector<std::pair<SourceLocation, Decl *>, 10>
index 657f2d92e37800139d66bab2d65c3949390c894a..f9da82dbb3b96f6a4c89402c08349c264526ae2c 100644 (file)
@@ -84,6 +84,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
+    ObjCShouldCallSuperDealloc(false),
     CompleteTranslationUnit(CompleteTranslationUnit),
     NumSFINAEErrors(0), SuppressAccessChecking(false), 
     AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
index 26af6ef97d1229f183c40266420ffed770780994..e45e7dafc62890b93446cecb919769017176e81c 100644 (file)
@@ -6690,10 +6690,17 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
       DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
                                              MD->getResultType(), MD);
     }
+    if (ObjCShouldCallSuperDealloc) {
+      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc);
+      ObjCShouldCallSuperDealloc = false;
+    }
   } else {
     return 0;
   }
 
+  assert(!ObjCShouldCallSuperDealloc && "This should only be set for "
+         "ObjC methods, which should have been handled in the block above.");
+
   // Verify and clean out per-function state.
   if (Body) {
     // C++ constructors that have function-try-blocks can't have return
index d255a3686ff2a8dc9405868dddac6bb211c816a9..35e32d4ad9d350add0ecd5a63d1e4140a1f558ab 100644 (file)
@@ -278,14 +278,22 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
     }
   }
 
-  // Warn on implementating deprecated methods under 
-  // -Wdeprecated-implementations flag.
-  if (ObjCInterfaceDecl *IC = MDecl->getClassInterface())
+  // Warn on deprecated methods under -Wdeprecated-implementations,
+  // and prepare for warning on missing super calls.
+  if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {
     if (ObjCMethodDecl *IMD = 
           IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()))
       DiagnoseObjCImplementedDeprecations(*this, 
                                           dyn_cast<NamedDecl>(IMD), 
                                           MDecl->getLocation(), 0);
+
+    // If this is "dealloc", set some bit here.
+    // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
+    // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
+    // Only do this if the current class actually has a superclass.
+    if (IC->getSuperClass())
+      ObjCShouldCallSuperDealloc = MDecl->getMethodFamily() == OMF_dealloc;
+  }
 }
 
 Decl *Sema::
index e88726b6d2a2a128bc6f2ab1121283636d6200bd..f3893ce2a587280475e000248c20cf3a92e3cfe2 100644 (file)
@@ -975,6 +975,9 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
   // We are in a method whose class has a superclass, so 'super'
   // is acting as a keyword.
   if (Method->isInstanceMethod()) {
+    if (Sel.getMethodFamily() == OMF_dealloc)
+      ObjCShouldCallSuperDealloc = false;
+
     // Since we are in an instance method, this is an instance
     // message to the superclass instance.
     QualType SuperTy = Context.getObjCInterfaceType(Super);
diff --git a/test/SemaObjC/warn-missing-super.m b/test/SemaObjC/warn-missing-super.m
new file mode 100644 (file)
index 0000000..8d04bf2
--- /dev/null
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@protocol NSCopying @end
+
+@interface NSObject <NSCopying>
+- (void)dealloc;
+@end
+
+@implementation NSObject
+- (void)dealloc {
+  // Root class, shouldn't warn
+}
+@end
+
+@interface Subclass1 : NSObject
+- (void)dealloc;
+@end
+
+@implementation Subclass1
+- (void)dealloc {
+}  // expected-warning{{method possibly missing a [super dealloc] call}}
+@end
+
+@interface Subclass2 : NSObject
+- (void)dealloc;
+@end
+
+@implementation Subclass2
+- (void)dealloc {
+  [super dealloc];  // Shouldn't warn
+}
+@end