ObjectiveC: under -Wunused-property-ivar warn if property's
backing warning is not used in one of its accessor methods.
// rdar://14989999
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193439 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2edebab..35bb3a3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1388,6 +1388,7 @@
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
+ DiagnoseUnusedBackingIvarInAccessor(S);
}
void Sema::ActOnStartFunctionDeclarator() {
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index d256658..be78767 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -3501,3 +3501,34 @@
}
return;
}
+
+ObjCIvarDecl *
+Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+ const ObjCPropertyDecl *&PDecl) const {
+
+ const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
+ if (!IDecl)
+ return 0;
+ Method = IDecl->lookupMethod(Method->getSelector(), true);
+ if (!Method || !Method->isPropertyAccessor())
+ return 0;
+ if ((PDecl = Method->findPropertyDecl()))
+ return PDecl->getPropertyIvarDecl();
+ return 0;
+}
+
+void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) {
+ if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodScope())
+ return;
+
+ const ObjCMethodDecl *CurMethod = getCurMethodDecl();
+ if (!CurMethod)
+ return;
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (IV && !IV->getBackingIvarReferencedInAccessor()) {
+ Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar)
+ << IV->getDeclName();
+ Diag(PDecl->getLocation(), diag::note_property_declare);
+ }
+}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 139bf5b..2fca0cd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2257,6 +2257,12 @@
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
+ // Mark this ivar 'referenced' in this method, if it is a backing ivar
+ // of a property and current method is one of its property accessor.
+ const ObjCPropertyDecl *PDecl;
+ const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
+ if (BIV && BIV == IV)
+ IV->setBackingIvarReferencedInAccessor(true);
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&