aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2011-08-22 17:25:57 +0000
committerNico Weber <nicolasweber@gmx.de>2011-08-22 17:25:57 +0000
commit9a1ecf0522ccb7a45577f856150c15af0ee1df2a (patch)
treedeaec3b3a32d6ea056a9f4e391bcc1c4a3e3bc21
parent0124839d7fb3d846795190ba2ccf3951f27784fe (diff)
Warn on missing [super dealloc] calls.
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
-rw-r--r--include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Sema/Sema.h5
-rw-r--r--lib/Sema/Sema.cpp1
-rw-r--r--lib/Sema/SemaDecl.cpp7
-rw-r--r--lib/Sema/SemaDeclObjC.cpp14
-rw-r--r--lib/Sema/SemaExprObjC.cpp3
-rw-r--r--test/SemaObjC/warn-missing-super.m32
8 files changed, 64 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index e7b061647c..add2ac365c 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -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
]>;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c76dca0f7b..89ffebbbab 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4bb014b88a..07bbd18bee 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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>
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 657f2d92e3..f9da82dbb3 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -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),
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 26af6ef97d..e45e7dafc6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d255a3686f..35e32d4ad9 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -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::
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index e88726b6d2..f3893ce2a5 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -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
index 0000000000..8d04bf2866
--- /dev/null
+++ b/test/SemaObjC/warn-missing-super.m
@@ -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