r193439 - ObjectiveC: under -Wunused-property-ivar warn if property's

Fariborz Jahanian fjahanian at apple.com
Fri Oct 25 14:44:51 PDT 2013


Author: fjahanian
Date: Fri Oct 25 16:44:50 2013
New Revision: 193439

URL: http://llvm.org/viewvc/llvm-project?rev=193439&view=rev
Log:
ObjectiveC: under -Wunused-property-ivar warn if property's
backing warning is not used in one of its accessor methods.
// rdar://14989999

Added:
    cfe/trunk/test/SemaObjC/unsued-backing-ivar-warning.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Fri Oct 25 16:44:50 2013
@@ -1246,10 +1246,12 @@ private:
   ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
                SourceLocation IdLoc, IdentifierInfo *Id,
                QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
-               bool synthesized)
+               bool synthesized,
+               bool backingIvarReferencedInAccessor)
     : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
                 /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
-      NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
+      NextIvar(0), DeclAccess(ac), Synthesized(synthesized),
+      BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {}
 
 public:
   static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
@@ -1257,7 +1259,8 @@ public:
                               IdentifierInfo *Id, QualType T,
                               TypeSourceInfo *TInfo,
                               AccessControl ac, Expr *BW = NULL,
-                              bool synthesized=false);
+                              bool synthesized=false,
+                              bool backingIvarReferencedInAccessor=false);
 
   static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
   
@@ -1279,6 +1282,13 @@ public:
     return DeclAccess == None ? Protected : AccessControl(DeclAccess);
   }
 
+  void setBackingIvarReferencedInAccessor(bool val) {
+    BackingIvarReferencedInAccessor = val;
+  }
+  bool getBackingIvarReferencedInAccessor() const {
+    return BackingIvarReferencedInAccessor;
+  }
+  
   void setSynthesize(bool synth) { Synthesized = synth; }
   bool getSynthesize() const { return Synthesized; }
 
@@ -1293,6 +1303,7 @@ private:
   // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
   unsigned DeclAccess : 3;
   unsigned Synthesized : 1;
+  unsigned BackingIvarReferencedInAccessor : 1;
 };
 
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Oct 25 16:44:50 2013
@@ -352,6 +352,7 @@ def UnusedValue : DiagGroup<"unused-valu
 def UnusedConstVariable : DiagGroup<"unused-const-variable">;
 def UnusedVariable : DiagGroup<"unused-variable",
                                [UnusedConstVariable]>;
+def UnusedPropertyIvar :  DiagGroup<"unused-property-ivar">;
 def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
 def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
 def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
@@ -437,7 +438,7 @@ def Unused : DiagGroup<"unused",
                         // UnusedParameter, (matches GCC's behavior)
                         // UnusedMemberFunction, (clean-up llvm before enabling)
                         UnusedPrivateField,
-                        UnusedValue, UnusedVariable]>,
+                        UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
                         DiagCategory<"Unused Entity Issue">;
 
 // Format settings.

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 25 16:44:50 2013
@@ -152,6 +152,10 @@ def warn_unused_parameter : Warning<"unu
   InGroup<UnusedParameter>, DefaultIgnore;
 def warn_unused_variable : Warning<"unused variable %0">,
   InGroup<UnusedVariable>, DefaultIgnore;
+def warn_unused_property_backing_ivar : 
+  Warning<"ivar %0 which backs the property is not "
+  "referenced in this property's accessor">,
+  InGroup<UnusedPropertyIvar>, DefaultIgnore;
 def warn_unused_const_variable : Warning<"unused variable %0">,
   InGroup<UnusedConstVariable>, DefaultIgnore;
 def warn_unused_exception_param : Warning<"unused exception parameter %0">,

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Oct 25 16:44:50 2013
@@ -2629,6 +2629,16 @@ public:
   bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
                                       ObjCMethodDecl *Method, ObjCIvarDecl *IV);
   
+  /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
+  /// backs the property is not used in the property's accessor.
+  void DiagnoseUnusedBackingIvarInAccessor(Scope *S);
+  
+  /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
+  /// it property has a backing ivar, returns this ivar; otherwise, returns NULL.
+  /// It also returns ivar's property on success.
+  ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+                                               const ObjCPropertyDecl *&PDecl) const;
+  
   /// Called by ActOnProperty to handle \@property declarations in
   /// class extensions.
   ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Fri Oct 25 16:44:50 2013
@@ -1241,6 +1241,8 @@ void ASTDumper::VisitObjCIvarDecl(const
   dumpType(D->getType());
   if (D->getSynthesize())
     OS << " synthesize";
+  if (D->getBackingIvarReferencedInAccessor())
+    OS << " BackingIvarReferencedInAccessor";
 
   switch (D->getAccessControl()) {
   case ObjCIvarDecl::None:

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Oct 25 16:44:50 2013
@@ -3017,7 +3017,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl
                                        Importer.Import(D->getInnerLocStart()),
                                               Loc, Name.getAsIdentifierInfo(),
                                               T, TInfo, D->getAccessControl(),
-                                              BitWidth, D->getSynthesize());
+                                              BitWidth, D->getSynthesize(),
+                                              D->getBackingIvarReferencedInAccessor());
   ToIvar->setLexicalDeclContext(LexicalDC);
   Importer.Imported(D, ToIvar);
   LexicalDC->addDeclInternal(ToIvar);

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Fri Oct 25 16:44:50 2013
@@ -1325,7 +1325,8 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTCo
                                    SourceLocation IdLoc, IdentifierInfo *Id,
                                    QualType T, TypeSourceInfo *TInfo,
                                    AccessControl ac, Expr *BW,
-                                   bool synthesized) {
+                                   bool synthesized,
+                                   bool backingIvarReferencedInAccessor) {
   if (DC) {
     // Ivar's can only appear in interfaces, implementations (via synthesized
     // properties), and class extensions (via direct declaration, or synthesized
@@ -1353,13 +1354,13 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTCo
   }
 
   return new (C) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo,
-                              ac, BW, synthesized);
+                              ac, BW, synthesized, backingIvarReferencedInAccessor);
 }
 
 ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCIvarDecl));
   return new (Mem) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0,
-                                QualType(), 0, ObjCIvarDecl::None, 0, false);
+                                QualType(), 0, ObjCIvarDecl::None, 0, false, false);
 }
 
 const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct 25 16:44:50 2013
@@ -1388,6 +1388,7 @@ void Sema::ActOnPopScope(SourceLocation
     // Remove this name from our lexical scope.
     IdResolver.RemoveDecl(D);
   }
+  DiagnoseUnusedBackingIvarInAccessor(S);
 }
 
 void Sema::ActOnStartFunctionDeclarator() {

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Oct 25 16:44:50 2013
@@ -3501,3 +3501,34 @@ void Sema::DiagnoseUseOfUnimplementedSel
   }
   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);
+  }
+}

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 25 16:44:50 2013
@@ -2257,6 +2257,12 @@ Sema::LookupInObjCMethod(LookupResult &L
         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 &&

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Oct 25 16:44:50 2013
@@ -798,6 +798,8 @@ void ASTDeclReader::VisitObjCIvarDecl(Ob
   IVD->setNextIvar(0);
   bool synth = Record[Idx++];
   IVD->setSynthesize(synth);
+  bool backingIvarReferencedInAccessor = Record[Idx++];
+  IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor);
 }
 
 void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=193439&r1=193438&r2=193439&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Oct 25 16:44:50 2013
@@ -528,6 +528,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(Ob
   // FIXME: stable encoding for @public/@private/@protected/@package
   Record.push_back(D->getAccessControl());
   Record.push_back(D->getSynthesize());
+  Record.push_back(D->getBackingIvarReferencedInAccessor());
 
   if (!D->hasAttrs() &&
       !D->isImplicit() &&
@@ -1505,6 +1506,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs()
   // ObjC Ivar
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize
+  // getBackingIvarReferencedInAccessor
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
   // Type Source Info
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));

Added: cfe/trunk/test/SemaObjC/unsued-backing-ivar-warning.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/unsued-backing-ivar-warning.m?rev=193439&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/unsued-backing-ivar-warning.m (added)
+++ cfe/trunk/test/SemaObjC/unsued-backing-ivar-warning.m Fri Oct 25 16:44:50 2013
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1  -fsyntax-only -Wunused-property-ivar -verify -Wno-objc-root-class %s
+// rdar://14989999
+
+ at interface NSObject @end
+
+ at interface Example : NSObject
+ at property (nonatomic, copy) id t; // expected-note {{property declared here}}
+ at property (nonatomic, copy) id u; // expected-note {{property declared here}}
+ at property (nonatomic, copy) id v; // expected-note {{property declared here}}
+ at property (nonatomic, copy) id w;
+ at property (nonatomic, copy) id x; // expected-note {{property declared here}}
+ at property (nonatomic, copy) id y; // expected-note {{property declared here}}
+ at property (nonatomic, copy) id z;
+ at property (nonatomic, copy) id ok;
+ at end
+
+ at implementation Example
+- (void) setX:(id)newX {  // expected-warning {{ivar '_x' which backs the property is not referenced in this property's accessor}}
+    _y = newX;
+}
+- (id) y { // expected-warning {{ivar '_y' which backs the property is not referenced in this property's accessor}}
+  return _v;
+}
+
+- (void) setV:(id)newV { // expected-warning {{ivar '_v' which backs the property is not referenced in this property's accessor}}
+    _y = newV;
+}
+
+// No warning here because there is no backing ivar.
+// both setter/getter are user defined.
+- (void) setW:(id)newW {
+    _y = newW;
+}
+- (id) w {
+  return _v;
+}
+
+- (id) u { // expected-warning {{ivar '_u' which backs the property is not referenced in this property's accessor}}
+  return _v;
+}
+
+ at synthesize ok = okIvar;
+- (void) setOk:(id)newOk {
+    okIvar = newOk;
+}
+
+ at synthesize t = tIvar;
+- (void) setT:(id)newT { // expected-warning {{ivar 'tIvar' which backs the property is not referenced in this property's accessor}}
+    okIvar = newT;
+}
+ at end





More information about the cfe-commits mailing list