aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Attr.td5
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaDeclAttr.cpp30
-rw-r--r--lib/Sema/SemaDeclObjC.cpp11
-rw-r--r--lib/Sema/SemaExprObjC.cpp8
-rw-r--r--test/SemaObjC/super-dealloc-attribute.m31
-rw-r--r--test/SemaObjC/warn-missing-super.m4
-rw-r--r--test/SemaObjCXX/warn-missing-super.mm2
9 files changed, 94 insertions, 8 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index fade83ef93..7406ce2647 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -528,6 +528,11 @@ def ObjCReturnsInnerPointer : Attr {
let Subjects = [ObjCMethod];
}
+def ObjCRequiresSuper : InheritableAttr {
+ let Spellings = [GNU<"objc_requires_super">];
+ let Subjects = [ObjCMethod];
+}
+
def ObjCRootClass : Attr {
let Spellings = [GNU<"objc_root_class">];
let Subjects = [ObjCInterface];
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 75c98b1159..2b6cb4c34e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -740,7 +740,7 @@ 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">,
+ "method possibly missing a [super %0] call">,
InGroup<ObjCMissingSuperCalls>;
def error_dealloc_bad_result_type : Error<
"dealloc return type must be correctly specified as 'void' under ARC, "
@@ -2057,6 +2057,12 @@ def warn_ns_attribute_wrong_parameter_type : Warning<
"%0 attribute only applies to %select{Objective-C object|pointer}1 "
"parameters">,
InGroup<IgnoredAttributes>;
+def warn_objc_requires_super_protocol : Warning<
+ "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">,
+ InGroup<DiagGroup<"requires-super-attribute">>;
+def note_protocol_decl : Note<
+ "protocol is declared here">;
+
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b3db840397..5ed06d6daa 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7832,7 +7832,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
computeNRVO(Body, getCurFunction());
}
if (getCurFunction()->ObjCShouldCallSuperDealloc) {
- Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc);
+ Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc)
+ << MD->getDeclName();
getCurFunction()->ObjCShouldCallSuperDealloc = false;
}
if (getCurFunction()->ObjCShouldCallSuperFinalize) {
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 8ffffab8b5..119ce7dfff 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3974,6 +3974,33 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context));
}
+static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
+ const AttributeList &attr) {
+ SourceLocation loc = attr.getLoc();
+ ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
+
+ if (!method) {
+ S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+ << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
+ return;
+ }
+ DeclContext *DC = method->getDeclContext();
+ if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
+ S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
+ << attr.getName() << 0;
+ S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
+ return;
+ }
+ if (method->getMethodFamily() == OMF_dealloc) {
+ S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
+ << attr.getName() << 1;
+ return;
+ }
+
+ method->addAttr(
+ ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context));
+}
+
/// Handle cf_audited_transfer and cf_unknown_transfer.
static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
if (!isa<FunctionDecl>(D)) {
@@ -4281,6 +4308,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCReturnsInnerPointer:
handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
+ case AttributeList::AT_ObjCRequiresSuper:
+ handleObjCRequiresSuperAttr(S, D, Attr); break;
+
case AttributeList::AT_NSBridged:
handleNSBridgedAttr(S, scope, D, Attr); break;
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index e800a6a7a4..709a868582 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -371,8 +371,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
// 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()))
+ ObjCMethodDecl *IMD =
+ IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());
+
+ if (IMD)
DiagnoseObjCImplementedDeprecations(*this,
dyn_cast<NamedDecl>(IMD),
MDecl->getLocation(), 0);
@@ -385,7 +387,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
getCurFunction()->ObjCShouldCallSuperDealloc =
!(Context.getLangOpts().ObjCAutoRefCount ||
Context.getLangOpts().getGC() == LangOptions::GCOnly) &&
- MDecl->getMethodFamily() == OMF_dealloc;
+ MDecl->getMethodFamily() == OMF_dealloc;
+ if (!getCurFunction()->ObjCShouldCallSuperDealloc)
+ getCurFunction()->ObjCShouldCallSuperDealloc =
+ (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>());
getCurFunction()->ObjCShouldCallSuperFinalize =
Context.getLangOpts().getGC() != LangOptions::NonGC &&
MDecl->getMethodFamily() == OMF_finalize;
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 17850bb2d7..58e28a9404 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1780,6 +1780,14 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
if (Method->isInstanceMethod()) {
if (Sel.getMethodFamily() == OMF_dealloc)
getCurFunction()->ObjCShouldCallSuperDealloc = false;
+ else if (const ObjCMethodDecl *IMD =
+ Class->lookupMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ // Must check for name of message since the method could
+ // be another method with objc_requires_super attribute set.
+ if (IMD->hasAttr<ObjCRequiresSuperAttr>() &&
+ Sel == IMD->getSelector())
+ getCurFunction()->ObjCShouldCallSuperDealloc = false;
if (Sel.getMethodFamily() == OMF_finalize)
getCurFunction()->ObjCShouldCallSuperFinalize = false;
diff --git a/test/SemaObjC/super-dealloc-attribute.m b/test/SemaObjC/super-dealloc-attribute.m
new file mode 100644
index 0000000000..c2da8e92af
--- /dev/null
+++ b/test/SemaObjC/super-dealloc-attribute.m
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fobjc-arc -fsyntax-only -verify -Wno-objc-root-class %s
+
+// rdar://6386358
+@protocol NSObject // expected-note {{protocol is declared here}}
+- MyDealloc __attribute((objc_requires_super)); // expected-warning {{'objc_requires_super' attribute cannot be applied to methods in protocols}}
+@end
+
+@interface Root
+- MyDealloc __attribute((objc_requires_super));
+- (void)XXX __attribute((objc_requires_super));
+- (void) dealloc __attribute((objc_requires_super)); // expected-warning {{'objc_requires_super' attribute cannot be applied to dealloc}}
+@end
+
+@interface Baz : Root<NSObject>
+- MyDealloc;
+@end
+
+@implementation Baz
+- MyDealloc {
+ [super MyDealloc];
+ return 0;
+}
+
+- (void)XXX {
+ [super MyDealloc];
+} // expected-warning {{method possibly missing a [super 'XXX'] call}}
+@end
+
diff --git a/test/SemaObjC/warn-missing-super.m b/test/SemaObjC/warn-missing-super.m
index 02b81651d7..ba65ec8c8d 100644
--- a/test/SemaObjC/warn-missing-super.m
+++ b/test/SemaObjC/warn-missing-super.m
@@ -41,11 +41,11 @@ __attribute__((objc_root_class))
@end
// RUN: %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
-// CHECK: warn-missing-super.m:24:1: warning: method possibly missing a [super dealloc] call
+// CHECK: warn-missing-super.m:24:1: warning: method possibly missing a [super 'dealloc'] call
// CHECK: 1 warning generated.
// RUN: %clang_cc1 -fsyntax-only -fobjc-gc %s 2>&1 | FileCheck --check-prefix=CHECK-GC %s
-// CHECK-GC: warn-missing-super.m:24:1: warning: method possibly missing a [super dealloc] call
+// CHECK-GC: warn-missing-super.m:24:1: warning: method possibly missing a [super 'dealloc'] call
// CHECK-GC: warn-missing-super.m:26:1: warning: method possibly missing a [super finalize] call
// CHECK-GC: 2 warnings generated.
diff --git a/test/SemaObjCXX/warn-missing-super.mm b/test/SemaObjCXX/warn-missing-super.mm
index cd2a6cca76..7383781535 100644
--- a/test/SemaObjCXX/warn-missing-super.mm
+++ b/test/SemaObjCXX/warn-missing-super.mm
@@ -15,5 +15,5 @@ template<typename T> struct shared_ptr {
- (void)dealloc
{
constexpr shared_ptr<int> dummy;
-} // expected-warning {{method possibly missing a [super dealloc] call}}
+} // expected-warning {{method possibly missing a [super 'dealloc'] call}}
@end